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

View File

@ -28,21 +28,40 @@ class BootImage {
unsigned stringMap; unsigned stringMap;
unsigned types; unsigned types;
uintptr_t codeBase;
unsigned callTable; unsigned callTable;
unsigned methodTree; unsigned methodTree;
unsigned methodTreeSentinal; unsigned methodTreeSentinal;
unsigned objectPools;
uintptr_t codeBase;
unsigned defaultThunk; unsigned defaultThunk;
unsigned nativeThunk; unsigned nativeThunk;
unsigned aioobThunk; 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" #include "thunks.cpp"
#undef THUNK #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 } // namespace vm
#endif//BOOTIMAGE_H #endif//BOOTIMAGE_H

View File

@ -1738,6 +1738,7 @@ compileDirectInvoke(MyThread* t, Frame* frame, object target)
} else { } else {
BootContext* bc = frame->context->bootContext; BootContext* bc = frame->context->bootContext;
if (bc) { if (bc) {
if (objectClass(t, target) == objectClass(t, frame->context->method)) {
Promise* p = new (bc->zone->allocate(sizeof(ListenPromise))) Promise* p = new (bc->zone->allocate(sizeof(ListenPromise)))
ListenPromise(t->m->system, bc->zone); ListenPromise(t->m->system, bc->zone);
@ -1751,6 +1752,14 @@ compileDirectInvoke(MyThread* t, Frame* frame, object target)
frame->trace(0, false), frame->trace(0, false),
rSize, rSize,
0); 0);
} else {
result = c->call
(c->constant(defaultThunk(t)),
Compiler::Aligned,
frame->trace(target, false),
rSize,
0);
}
} else if (methodCompiled(t, target) == defaultThunk(t)) { } else if (methodCompiled(t, target) == defaultThunk(t)) {
result = c->call result = c->call
(c->constant(defaultThunk(t)), (c->constant(defaultThunk(t)),
@ -4654,6 +4663,31 @@ class SegFaultHandler: public System::SignalHandler {
Machine* m; 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 { class FixedAllocator: public Allocator {
public: public:
FixedAllocator(Thread* t, uint8_t* base, unsigned capacity): FixedAllocator(Thread* t, uint8_t* base, unsigned capacity):
@ -5073,7 +5107,43 @@ class MyProcessor: public Processor {
image->callTable = w->visitRoot(callTable); image->callTable = w->visitRoot(callTable);
image->methodTree = w->visitRoot(methodTree); image->methodTree = w->visitRoot(methodTree);
image->methodTreeSentinal = w->visitRoot(methodTreeSentinal); 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; System* s;
@ -5183,38 +5253,47 @@ compileThunks(MyThread* t, Allocator* allocator, MyProcessor* p,
p->defaultThunk = finish p->defaultThunk = finish
(t, allocator, defaultContext.context.assembler, "default"); (t, allocator, defaultContext.context.assembler, "default");
{ void* p = defaultContext.promise.listener->resolve { void* call = defaultContext.promise.listener->resolve
(reinterpret_cast<intptr_t>(voidPointer(compileMethod))); (reinterpret_cast<intptr_t>(voidPointer(compileMethod)));
if (image) { 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 p->nativeThunk = finish
(t, allocator, nativeContext.context.assembler, "native"); (t, allocator, nativeContext.context.assembler, "native");
{ void* p = nativeContext.promise.listener->resolve { void* call = nativeContext.promise.listener->resolve
(reinterpret_cast<intptr_t>(voidPointer(invokeNative))); (reinterpret_cast<intptr_t>(voidPointer(invokeNative)));
if (image) { 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 p->aioobThunk = finish
(t, allocator, aioobContext.context.assembler, "aioob"); (t, allocator, aioobContext.context.assembler, "aioob");
{ void* p = aioobContext.promise.listener->resolve { void* call = aioobContext.promise.listener->resolve
(reinterpret_cast<intptr_t>(voidPointer(throwArrayIndexOutOfBounds))); (reinterpret_cast<intptr_t>(voidPointer(throwArrayIndexOutOfBounds)));
if (image) { 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*> p->thunkTable = static_cast<uint8_t*>
(allocator->allocate(p->thunkSize * ThunkCount)); (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); logCompile(t, p->thunkTable, p->thunkSize * ThunkCount, 0, "thunkTable", 0);
uint8_t* start = p->thunkTable; uint8_t* start = p->thunkTable;
@ -5222,10 +5301,10 @@ compileThunks(MyThread* t, Allocator* allocator, MyProcessor* p,
#define THUNK(s) \ #define THUNK(s) \
tableContext.context.assembler->writeTo(start); \ tableContext.context.assembler->writeTo(start); \
start += p->thunkSize; \ start += p->thunkSize; \
{ void* p = tableContext.promise.listener->resolve \ { void* call = tableContext.promise.listener->resolve \
(reinterpret_cast<intptr_t>(voidPointer(s))); \ (reinterpret_cast<intptr_t>(voidPointer(s))); \
if (image) { \ 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); for (; word <= wordLimit and (word < wordLimit or bit < bitLimit);
++word) ++word)
{ {
uintptr_t* p = map->data() + word; uintptr_t w = map->data()[word];
if (*p) { if (2) {
for (; bit < BitsPerWord and (word < wordLimit or bit < bitLimit); for (; bit < BitsPerWord and (word < wordLimit or bit < bitLimit);
++bit) ++bit)
{ {
if (map->data()[word] & (static_cast<uintptr_t>(1) << bit)) { if (w & (static_cast<uintptr_t>(1) << bit)) {
index = ::indexOf(word, bit); index = ::indexOf(word, bit);
// printf("hit at index %d\n", index); // printf("hit at index %d\n", index);
return true; 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); 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 { class HeapClient: public Heap::Client {
public: public:
HeapClient(Machine* m): m(m) { } HeapClient(Machine* m): m(m) { }
@ -1716,86 +1866,30 @@ Thread::init()
abort(this); 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); unsigned size;
memset(t->m->loader, 0, sizeof(void*) * 2); image = function(&size);
}
}
t->m->types = allocate(t, pad((TypeCount + 2) * BytesPerWord), true); if (image) {
arrayLength(t, t->m->types) = TypeCount; boot(this, image);
memset(&arrayBody(t, t->m->types, 0), 0, TypeCount * BytesPerWord); } else {
boot(this);
#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);
} }
m->monitorMap = makeWeakHashMap(this, 0, 0); m->monitorMap = makeWeakHashMap(this, 0, 0);
m->stringMap = makeWeakHashMap(this, 0, 0);
m->jniMethodTable = makeVector(this, 0, 0, false); m->jniMethodTable = makeVector(this, 0, 0, false);
m->localThread->set(this); 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 { } else {
peer = parent->child; peer = parent->child;
parent->child = this; parent->child = this;

View File

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