diff --git a/src/bootimage.cpp b/src/bootimage.cpp index 7179328580..e57cfd0f3f 100644 --- a/src/bootimage.cpp +++ b/src/bootimage.cpp @@ -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 diff --git a/src/bootimage.h b/src/bootimage.h index 2e09e44d89..cfd73171d1 100644 --- a/src/bootimage.h +++ b/src/bootimage.h @@ -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 diff --git a/src/compile.cpp b/src/compile.cpp index 3441be0dae..4c68c5bf95 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -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(heap + image->methodTree); + methodTreeSentinal = reinterpret_cast + (heap + image->methodTreeSentinal); + + callTable = fixupCallTable + (static_cast(t), + reinterpret_cast(heap + image->callTable), + image->codeBase, + reinterpret_cast(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(voidPointer(compileMethod))); if (image) { - image->defaultThunk = static_cast(p) - imageBase; + image->defaultThunk = p->defaultThunk - imageBase; + image->compileMethodCall = static_cast(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(voidPointer(invokeNative))); if (image) { - image->nativeThunk = static_cast(p) - imageBase; + image->nativeThunk = p->nativeThunk - imageBase; + image->invokeNativeCall = static_cast(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(voidPointer(throwArrayIndexOutOfBounds))); if (image) { - image->aioobThunk = static_cast(p) - imageBase; + image->aioobThunk = p->aioobThunk - imageBase; + image->throwArrayIndexOutOfBoundsCall + = static_cast(call) - imageBase; } } p->thunkTable = static_cast (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(voidPointer(s))); \ if (image) { \ - image->s##Thunk = static_cast(p) - imageBase; \ + image->s##Call = static_cast(call) - imageBase; \ } \ } diff --git a/src/heap.cpp b/src/heap.cpp index a70f176b3e..93fb925b2d 100644 --- a/src/heap.cpp +++ b/src/heap.cpp @@ -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(1) << bit)) { + if (w & (static_cast(1) << bit)) { index = ::indexOf(word, bit); // printf("hit at index %d\n", index); return true; diff --git a/src/machine.cpp b/src/machine.cpp index dd9b4cdd4f..78a0063995 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -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(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(1) << bit)) { + unsigned index = ::indexOf(word, bit); + uintptr_t* p = heap + index; + if (*p) { + *p = reinterpret_cast(heap + *p - 1); + } + } + } + } + } + + t->m->loader = reinterpret_cast(heap + image->loader); + t->m->stringMap = reinterpret_cast(heap + image->stringMap); + t->m->types = reinterpret_cast(heap + image->types); + + uintptr_t* codeMap = heap + ceiling(image->heapSize, BytesPerWord); + unsigned codeMapSizeInWords = ceiling + (codeMapSize(image->codeSize), BytesPerWord); + uint8_t* code = reinterpret_cast(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(1) << bit)) { + unsigned index = ::indexOf(word, bit); + uintptr_t v; memcpy(&v, code + index, BytesPerWord); + if (v) { + v = reinterpret_cast(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(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; diff --git a/src/processor.h b/src/processor.h index 621bd5460a..ee5d728de3 100644 --- a/src/processor.h +++ b/src/processor.h @@ -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_, ...) {