initial work on booting from boot image

This commit is contained in:
Joel Dice 2008-11-28 15:02:45 -07:00
parent d22a9ab270
commit 4d1af63ed2
6 changed files with 303 additions and 117 deletions

View File

@ -31,12 +31,6 @@ endsWith(const char* suffix, const char* s, unsigned length)
and memcmp(suffix, s + (length - suffixLength), suffixLength) == 0;
}
unsigned
codeMapSize(unsigned codeSize)
{
return ceiling(codeSize, BitsPerWord) * BytesPerWord;
}
object
makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code,
unsigned capacity)
@ -82,12 +76,6 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code,
return constants;
}
unsigned
heapMapSize(unsigned heapSize)
{
return ceiling(heapSize, BitsPerWord * 8) * BytesPerWord;
}
unsigned
objectSize(Thread* t, object o)
{
@ -238,15 +226,18 @@ writeBootImage(Thread* t, FILE* out)
image.magic = BootImage::Magic;
// fprintf(stderr, "heap size %d code size %d\n",
// image.heapSize, image.codeSize);
fwrite(&image, sizeof(BootImage), 1, out);
if (true) {
fprintf(stderr, "heap size %d code size %d\n",
image.heapSize, image.codeSize);
} else {
fwrite(&image, sizeof(BootImage), 1, out);
fwrite(heapMap, pad(heapMapSize(image.heapSize)), 1, out);
fwrite(heap, pad(image.heapSize), 1, out);
fwrite(heapMap, pad(heapMapSize(image.heapSize)), 1, out);
fwrite(heap, pad(image.heapSize), 1, out);
fwrite(codeMap, pad(codeMapSize(image.codeSize)), 1, out);
fwrite(code, pad(image.codeSize), 1, out);
fwrite(codeMap, pad(codeMapSize(image.codeSize)), 1, out);
fwrite(code, pad(image.codeSize), 1, out);
}
}
} // namespace

View File

@ -28,21 +28,40 @@ class BootImage {
unsigned stringMap;
unsigned types;
uintptr_t codeBase;
unsigned callTable;
unsigned methodTree;
unsigned methodTreeSentinal;
unsigned objectPools;
uintptr_t codeBase;
unsigned defaultThunk;
unsigned nativeThunk;
unsigned aioobThunk;
#define THUNK(s) unsigned s##Thunk;
unsigned thunkTable;
unsigned thunkSize;
unsigned compileMethodCall;
unsigned invokeNativeCall;
unsigned throwArrayIndexOutOfBoundsCall;
#define THUNK(s) unsigned s##Call;
#include "thunks.cpp"
#undef THUNK
};
inline unsigned
codeMapSize(unsigned codeSize)
{
return ceiling(codeSize, BitsPerWord) * BytesPerWord;
}
inline unsigned
heapMapSize(unsigned heapSize)
{
return ceiling(heapSize, BitsPerWord * 8) * BytesPerWord;
}
} // namespace vm
#endif//BOOTIMAGE_H

View File

@ -1738,19 +1738,28 @@ compileDirectInvoke(MyThread* t, Frame* frame, object target)
} else {
BootContext* bc = frame->context->bootContext;
if (bc) {
Promise* p = new (bc->zone->allocate(sizeof(ListenPromise)))
ListenPromise(t->m->system, bc->zone);
if (objectClass(t, target) == objectClass(t, frame->context->method)) {
Promise* p = new (bc->zone->allocate(sizeof(ListenPromise)))
ListenPromise(t->m->system, bc->zone);
PROTECT(t, target);
object pointer = makePointer(t, p);
bc->calls = makeTriple(t, target, pointer, bc->calls);
PROTECT(t, target);
object pointer = makePointer(t, p);
bc->calls = makeTriple(t, target, pointer, bc->calls);
result = c->call
(c->promiseConstant(p),
0,
frame->trace(0, false),
rSize,
0);
result = c->call
(c->promiseConstant(p),
0,
frame->trace(0, false),
rSize,
0);
} else {
result = c->call
(c->constant(defaultThunk(t)),
Compiler::Aligned,
frame->trace(target, false),
rSize,
0);
}
} else if (methodCompiled(t, target) == defaultThunk(t)) {
result = c->call
(c->constant(defaultThunk(t)),
@ -4654,6 +4663,31 @@ class SegFaultHandler: public System::SignalHandler {
Machine* m;
};
object
fixupCallTable(MyThread* t, object oldTable, uintptr_t oldBase,
uintptr_t newBase)
{
PROTECT(t, oldTable);
object newTable = makeArray(t, arrayLength(t, oldTable), true);
for (unsigned i = 0; i < arrayLength(t, oldTable); ++i) {
object next;
for (object p = arrayBody(t, oldTable, i); p; p = next) {
next = callNodeNext(t, p);
intptr_t k = (callNodeAddress(t, p) - oldBase) + newBase;
unsigned index = k & (arrayLength(t, newTable) - 1);
set(t, p, CallNodeNext, arrayBody(t, newTable, index));
set(t, newTable, ArrayBody + (index * BytesPerWord), p);
}
}
return newTable;
}
class FixedAllocator: public Allocator {
public:
FixedAllocator(Thread* t, uint8_t* base, unsigned capacity):
@ -5073,7 +5107,43 @@ class MyProcessor: public Processor {
image->callTable = w->visitRoot(callTable);
image->methodTree = w->visitRoot(methodTree);
image->methodTreeSentinal = w->visitRoot(methodTreeSentinal);
image->objectPools = w->visitRoot(objectPools);
}
virtual void boot(Thread* t, BootImage* image, uintptr_t* heap,
uint8_t* code)
{
methodTree = reinterpret_cast<object>(heap + image->methodTree);
methodTreeSentinal = reinterpret_cast<object>
(heap + image->methodTreeSentinal);
callTable = fixupCallTable
(static_cast<MyThread*>(t),
reinterpret_cast<object>(heap + image->callTable),
image->codeBase,
reinterpret_cast<uintptr_t>(code));
defaultThunk = code + image->defaultThunk;
{ void* p = voidPointer(::compileMethod);
memcpy(code + image->compileMethodCall, &p, BytesPerWord); }
nativeThunk = code + image->nativeThunk;
{ void* p = voidPointer(invokeNative);
memcpy(code + image->invokeNativeCall, &p, BytesPerWord); }
aioobThunk = code + image->aioobThunk;
{ void* p = voidPointer(throwArrayIndexOutOfBounds);
memcpy(code + image->throwArrayIndexOutOfBoundsCall, &p, BytesPerWord); }
thunkTable = code + image->thunkTable;
thunkSize = image->thunkSize;
#define THUNK(s) \
{ void* p = voidPointer(s); \
memcpy(code + image->s##Call, &p, BytesPerWord); }
#include "thunks.cpp"
#undef THUNK
}
System* s;
@ -5183,38 +5253,47 @@ compileThunks(MyThread* t, Allocator* allocator, MyProcessor* p,
p->defaultThunk = finish
(t, allocator, defaultContext.context.assembler, "default");
{ void* p = defaultContext.promise.listener->resolve
{ void* call = defaultContext.promise.listener->resolve
(reinterpret_cast<intptr_t>(voidPointer(compileMethod)));
if (image) {
image->defaultThunk = static_cast<uint8_t*>(p) - imageBase;
image->defaultThunk = p->defaultThunk - imageBase;
image->compileMethodCall = static_cast<uint8_t*>(call) - imageBase;
}
}
p->nativeThunk = finish
(t, allocator, nativeContext.context.assembler, "native");
{ void* p = nativeContext.promise.listener->resolve
{ void* call = nativeContext.promise.listener->resolve
(reinterpret_cast<intptr_t>(voidPointer(invokeNative)));
if (image) {
image->nativeThunk = static_cast<uint8_t*>(p) - imageBase;
image->nativeThunk = p->nativeThunk - imageBase;
image->invokeNativeCall = static_cast<uint8_t*>(call) - imageBase;
}
}
p->aioobThunk = finish
(t, allocator, aioobContext.context.assembler, "aioob");
{ void* p = aioobContext.promise.listener->resolve
{ void* call = aioobContext.promise.listener->resolve
(reinterpret_cast<intptr_t>(voidPointer(throwArrayIndexOutOfBounds)));
if (image) {
image->aioobThunk = static_cast<uint8_t*>(p) - imageBase;
image->aioobThunk = p->aioobThunk - imageBase;
image->throwArrayIndexOutOfBoundsCall
= static_cast<uint8_t*>(call) - imageBase;
}
}
p->thunkTable = static_cast<uint8_t*>
(allocator->allocate(p->thunkSize * ThunkCount));
if (image) {
image->thunkTable = p->thunkTable - imageBase;
image->thunkSize = p->thunkSize;
}
logCompile(t, p->thunkTable, p->thunkSize * ThunkCount, 0, "thunkTable", 0);
uint8_t* start = p->thunkTable;
@ -5222,10 +5301,10 @@ compileThunks(MyThread* t, Allocator* allocator, MyProcessor* p,
#define THUNK(s) \
tableContext.context.assembler->writeTo(start); \
start += p->thunkSize; \
{ void* p = tableContext.promise.listener->resolve \
{ void* call = tableContext.promise.listener->resolve \
(reinterpret_cast<intptr_t>(voidPointer(s))); \
if (image) { \
image->s##Thunk = static_cast<uint8_t*>(p) - imageBase; \
image->s##Call = static_cast<uint8_t*>(call) - imageBase; \
} \
}

View File

@ -121,12 +121,12 @@ class Segment {
for (; word <= wordLimit and (word < wordLimit or bit < bitLimit);
++word)
{
uintptr_t* p = map->data() + word;
if (*p) {
uintptr_t w = map->data()[word];
if (2) {
for (; bit < BitsPerWord and (word < wordLimit or bit < bitLimit);
++bit)
{
if (map->data()[word] & (static_cast<uintptr_t>(1) << bit)) {
if (w & (static_cast<uintptr_t>(1) << bit)) {
index = ::indexOf(word, bit);
// printf("hit at index %d\n", index);
return true;

View File

@ -1502,6 +1502,156 @@ bootJavaClass(Thread* t, Machine::Type type, int superType, const char* name,
hashMapInsert(t, t->m->bootstrapClassMap, n, class_, byteArrayHash);
}
void
boot(Thread* t, BootImage* image)
{
assert(t, image->magic == BootImage::Magic);
uintptr_t* heapMap = reinterpret_cast<uintptr_t*>(image + 1);
unsigned heapMapSizeInWords = ceiling
(heapMapSize(image->heapSize), BytesPerWord);
uintptr_t* heap = heapMap + heapMapSizeInWords;
for (unsigned word = 0; word < heapMapSizeInWords; ++word) {
uintptr_t w = heapMap[word];
if (w) {
for (unsigned bit = 0; bit < BitsPerWord; ++bit) {
if (w & (static_cast<uintptr_t>(1) << bit)) {
unsigned index = ::indexOf(word, bit);
uintptr_t* p = heap + index;
if (*p) {
*p = reinterpret_cast<uintptr_t>(heap + *p - 1);
}
}
}
}
}
t->m->loader = reinterpret_cast<object>(heap + image->loader);
t->m->stringMap = reinterpret_cast<object>(heap + image->stringMap);
t->m->types = reinterpret_cast<object>(heap + image->types);
uintptr_t* codeMap = heap + ceiling(image->heapSize, BytesPerWord);
unsigned codeMapSizeInWords = ceiling
(codeMapSize(image->codeSize), BytesPerWord);
uint8_t* code = reinterpret_cast<uint8_t*>(codeMap + codeMapSizeInWords);
for (unsigned word = 0; word < codeMapSizeInWords; ++word) {
uintptr_t w = codeMap[word];
if (w) {
for (unsigned bit = 0; bit < BitsPerWord; ++bit) {
if (w & (static_cast<uintptr_t>(1) << bit)) {
unsigned index = ::indexOf(word, bit);
uintptr_t v; memcpy(&v, code + index, BytesPerWord);
if (v) {
v = reinterpret_cast<uintptr_t>(heap + v - 1);
memcpy(code + index, &v, BytesPerWord);
}
}
}
}
}
t->m->processor->boot(t, image, heap, code);
for (HashMapIterator it(t, systemClassLoaderMap(t, t->m->loader));
it.hasMore();)
{
object c = tripleSecond(t, it.next());
if (classMethodTable(t, c)) {
for (unsigned i = 0; i < arrayLength(t, classMethodTable(t, c)); ++i) {
object method = arrayBody(t, classMethodTable(t, c), i);
methodCompiled(t, method)
= (methodCompiled(t, method) - image->codeBase)
+ reinterpret_cast<uintptr_t>(code);
}
}
t->m->processor->initVtable(t, c);
}
}
void
boot(Thread* t)
{
Machine* m = t->m;
m->loader = allocate(t, sizeof(void*) * 3, true);
memset(m->loader, 0, sizeof(void*) * 2);
m->types = allocate(t, pad((TypeCount + 2) * BytesPerWord), true);
arrayLength(t, m->types) = TypeCount;
memset(&arrayBody(t, m->types, 0), 0, TypeCount * BytesPerWord);
#include "type-initializations.cpp"
object arrayClass = arrayBody(t, m->types, Machine::ArrayType);
set(t, m->types, 0, arrayClass);
object loaderClass = arrayBody
(t, m->types, Machine::SystemClassLoaderType);
set(t, m->loader, 0, loaderClass);
object objectClass = arrayBody(t, m->types, Machine::JobjectType);
object classClass = arrayBody(t, m->types, Machine::ClassType);
set(t, classClass, 0, classClass);
set(t, classClass, ClassSuper, objectClass);
object intArrayClass = arrayBody(t, m->types, Machine::IntArrayType);
set(t, intArrayClass, 0, classClass);
set(t, intArrayClass, ClassSuper, objectClass);
m->unsafe = false;
classVmFlags(t, arrayBody(t, m->types, Machine::SingletonType))
|= SingletonFlag;
classVmFlags(t, arrayBody(t, m->types, Machine::JreferenceType))
|= ReferenceFlag;
classVmFlags(t, arrayBody(t, m->types, Machine::WeakReferenceType))
|= ReferenceFlag | WeakReferenceFlag;
classVmFlags(t, arrayBody(t, m->types, Machine::PhantomReferenceType))
|= ReferenceFlag | WeakReferenceFlag;
classVmFlags(t, arrayBody(t, m->types, Machine::JbooleanType))
|= PrimitiveFlag;
classVmFlags(t, arrayBody(t, m->types, Machine::JbyteType))
|= PrimitiveFlag;
classVmFlags(t, arrayBody(t, m->types, Machine::JcharType))
|= PrimitiveFlag;
classVmFlags(t, arrayBody(t, m->types, Machine::JshortType))
|= PrimitiveFlag;
classVmFlags(t, arrayBody(t, m->types, Machine::JintType))
|= PrimitiveFlag;
classVmFlags(t, arrayBody(t, m->types, Machine::JlongType))
|= PrimitiveFlag;
classVmFlags(t, arrayBody(t, m->types, Machine::JfloatType))
|= PrimitiveFlag;
classVmFlags(t, arrayBody(t, m->types, Machine::JdoubleType))
|= PrimitiveFlag;
classVmFlags(t, arrayBody(t, m->types, Machine::JvoidType))
|= PrimitiveFlag;
m->bootstrapClassMap = makeHashMap(t, 0, 0);
{ object loaderMap = makeHashMap(t, 0, 0);
set(t, m->loader, SystemClassLoaderMap, loaderMap);
}
m->stringMap = makeWeakHashMap(t, 0, 0);
{ object bootCode = makeCode(t, 0, 0, 0, 0, 0, 1, false);
codeBody(t, bootCode, 0) = impdep1;
object bootMethod = makeMethod
(t, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, bootCode, 0);
PROTECT(t, bootMethod);
#include "type-java-initializations.cpp"
}
}
class HeapClient: public Heap::Client {
public:
HeapClient(Machine* m): m(m) { }
@ -1716,86 +1866,30 @@ Thread::init()
abort(this);
}
Thread* t = this;
BootImage* image = 0;
const char* imageFunctionName = findProperty(m, "avian.bootimage");
if (imageFunctionName) {
void* p = m->libraries->resolve(imageFunctionName);
if (p) {
BootImage* (*function)(unsigned*);
memcpy(&function, &p, BytesPerWord);
t->m->loader = allocate(t, sizeof(void*) * 3, true);
memset(t->m->loader, 0, sizeof(void*) * 2);
unsigned size;
image = function(&size);
}
}
t->m->types = allocate(t, pad((TypeCount + 2) * BytesPerWord), true);
arrayLength(t, t->m->types) = TypeCount;
memset(&arrayBody(t, t->m->types, 0), 0, TypeCount * BytesPerWord);
#include "type-initializations.cpp"
object arrayClass = arrayBody(t, t->m->types, Machine::ArrayType);
set(t, t->m->types, 0, arrayClass);
object loaderClass = arrayBody
(t, t->m->types, Machine::SystemClassLoaderType);
set(t, t->m->loader, 0, loaderClass);
object objectClass = arrayBody(t, m->types, Machine::JobjectType);
object classClass = arrayBody(t, m->types, Machine::ClassType);
set(t, classClass, 0, classClass);
set(t, classClass, ClassSuper, objectClass);
object intArrayClass = arrayBody(t, m->types, Machine::IntArrayType);
set(t, intArrayClass, 0, classClass);
set(t, intArrayClass, ClassSuper, objectClass);
m->unsafe = false;
classVmFlags(t, arrayBody(t, m->types, Machine::SingletonType))
|= SingletonFlag;
classVmFlags(t, arrayBody(t, m->types, Machine::JreferenceType))
|= ReferenceFlag;
classVmFlags(t, arrayBody(t, m->types, Machine::WeakReferenceType))
|= ReferenceFlag | WeakReferenceFlag;
classVmFlags(t, arrayBody(t, m->types, Machine::PhantomReferenceType))
|= ReferenceFlag | WeakReferenceFlag;
classVmFlags(t, arrayBody(t, m->types, Machine::JbooleanType))
|= PrimitiveFlag;
classVmFlags(t, arrayBody(t, m->types, Machine::JbyteType))
|= PrimitiveFlag;
classVmFlags(t, arrayBody(t, m->types, Machine::JcharType))
|= PrimitiveFlag;
classVmFlags(t, arrayBody(t, m->types, Machine::JshortType))
|= PrimitiveFlag;
classVmFlags(t, arrayBody(t, m->types, Machine::JintType))
|= PrimitiveFlag;
classVmFlags(t, arrayBody(t, m->types, Machine::JlongType))
|= PrimitiveFlag;
classVmFlags(t, arrayBody(t, m->types, Machine::JfloatType))
|= PrimitiveFlag;
classVmFlags(t, arrayBody(t, m->types, Machine::JdoubleType))
|= PrimitiveFlag;
classVmFlags(t, arrayBody(t, m->types, Machine::JvoidType))
|= PrimitiveFlag;
m->bootstrapClassMap = makeHashMap(this, 0, 0);
{ object loaderMap = makeHashMap(this, 0, 0);
set(t, m->loader, SystemClassLoaderMap, loaderMap);
if (image) {
boot(this, image);
} else {
boot(this);
}
m->monitorMap = makeWeakHashMap(this, 0, 0);
m->stringMap = makeWeakHashMap(this, 0, 0);
m->jniMethodTable = makeVector(this, 0, 0, false);
m->localThread->set(this);
{ object bootCode = makeCode(t, 0, 0, 0, 0, 0, 1, false);
codeBody(t, bootCode, 0) = impdep1;
object bootMethod = makeMethod
(t, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, bootCode, 0);
PROTECT(t, bootMethod);
#include "type-java-initializations.cpp"
}
} else {
peer = parent->child;
parent->child = this;

View File

@ -127,6 +127,9 @@ class Processor {
virtual void
visitRoots(BootImage* image, HeapWalker* w) = 0;
virtual void
boot(Thread* t, BootImage* image, uintptr_t* heap, uint8_t* code) = 0;
object
invoke(Thread* t, object method, object this_, ...)
{