diff --git a/src/assembler.h b/src/assembler.h index 7d3946274c..0677178e68 100644 --- a/src/assembler.h +++ b/src/assembler.h @@ -129,6 +129,33 @@ class ListenPromise: public Promise { System* s; Allocator* allocator; Listener* listener; + Promise* promise; +}; + +class DelayedPromise: public ListenPromise { + public: + DelayedPromise(System* s, Allocator* allocator, Promise* basis, + DelayedPromise* next): + ListenPromise(s, allocator), basis(basis), next(next) + { } + + virtual int64_t value() { + abort(s); + } + + virtual bool resolved() { + return false; + } + + virtual Listener* listen(unsigned sizeInBytes) { + Listener* l = static_cast(allocator->allocate(sizeInBytes)); + l->next = listener; + listener = l; + return l; + } + + Promise* basis; + DelayedPromise* next; }; class TraceHandler { diff --git a/src/bootimage.cpp b/src/bootimage.cpp index aa368258e0..7f7d12fc8f 100644 --- a/src/bootimage.cpp +++ b/src/bootimage.cpp @@ -33,7 +33,7 @@ endsWith(const char* suffix, const char* s, unsigned length) object makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, - unsigned capacity) + unsigned capacity, uintptr_t* codeMap) { unsigned size = 0; t->m->processor->compileThunks(t, image, code, &size, capacity); @@ -44,6 +44,8 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, object calls = 0; PROTECT(t, calls); + DelayedPromise* addresses = 0; + for (Finder::Iterator it(t->m->finder); it.hasMore();) { unsigned nameSize; const char* name = it.next(&nameSize); @@ -59,7 +61,8 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, object method = arrayBody(t, classMethodTable(t, c), i); if (methodCode(t, method) or (methodFlags(t, method) & ACC_NATIVE)) { t->m->processor->compileMethod - (t, zone, code, &size, capacity, &constants, &calls, method); + (t, zone, code, &size, capacity, &constants, &calls, &addresses, + method); } } } @@ -79,6 +82,19 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, ->listener->resolve(address); } + for (; addresses; addresses = addresses->next) { + uint8_t* value = reinterpret_cast(addresses->basis->value()); + assert(t, value >= code); + + void* dst = addresses->listener->resolve + ((value - code) | (1 << BootShift)); + assert(t, reinterpret_cast(dst) + >= reinterpret_cast(code)); + + markBit(codeMap, reinterpret_cast(dst) + - reinterpret_cast(code)); + } + image->codeSize = size; return constants; @@ -250,7 +266,8 @@ writeBootImage(Thread* t, FILE* out) (t->m->heap->allocate(codeMapSize(CodeCapacity))); memset(codeMap, 0, codeMapSize(CodeCapacity)); - object constants = makeCodeImage(t, &zone, &image, code, CodeCapacity); + object constants = makeCodeImage + (t, &zone, &image, code, CodeCapacity, codeMap); PROTECT(t, constants); const unsigned HeapCapacity = 32 * 1024 * 1024; diff --git a/src/compile.cpp b/src/compile.cpp index 18c670a74f..bf84652cb0 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -466,13 +466,17 @@ class BootContext { BootContext* c; }; - BootContext(Thread* t, object constants, object calls, Zone* zone): - protector(t, this), constants(constants), calls(calls), zone(zone) + BootContext(Thread* t, object constants, object calls, + DelayedPromise* addresses, Zone* zone): + protector(t, this), constants(constants), calls(calls), + addresses(addresses), addressSentinal(addresses), zone(zone) { } MyProtector protector; object constants; object calls; + DelayedPromise* addresses; + DelayedPromise* addressSentinal; Zone* zone; }; @@ -856,6 +860,21 @@ class Frame { set(sp - 2, saved); } + Promise* addressPromise(Promise* p) { + BootContext* bc = context->bootContext; + if (bc) { + bc->addresses = new (bc->zone->allocate(sizeof(DelayedPromise))) + DelayedPromise(t->m->system, bc->zone, p, bc->addresses); + return bc->addresses; + } else { + return p; + } + } + + Compiler::Operand* addressOperand(Promise* p) { + return c->promiseConstant(addressPromise(p)); + } + Compiler::Operand* machineIp(unsigned logicalIp) { return c->promiseConstant(c->machineIp(logicalIp)); } @@ -2997,7 +3016,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, c->saveStack(); - frame->pushAddress(frame->machineIp(ip)); + frame->pushAddress(frame->addressOperand(c->machineIp(ip))); c->jmp(frame->machineIp(newIp)); // NB: we assume that the stack will look the same on return @@ -3145,8 +3164,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, uint32_t defaultIp = base + codeReadInt32(t, code, ip); assert(t, defaultIp < codeLength(t, code)); - Compiler::Operand* default_ = c->address - (c->poolAppendPromise(c->machineIp(defaultIp))); + Compiler::Operand* default_ = frame->addressOperand + (c->machineIp(defaultIp)); int32_t pairCount = codeReadInt32(t, code, ip); @@ -3162,9 +3181,9 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, Promise* p = c->poolAppend(key); if (i == 0) { - start = c->promiseConstant(p); + start = frame->addressOperand(p); } - c->poolAppendPromise(c->machineIp(newIp)); + c->poolAppendPromise(frame->addressPromise(c->machineIp(newIp))); } assert(t, start); @@ -3475,9 +3494,10 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, ipTable[i] = newIp; - Promise* p = c->poolAppendPromise(c->machineIp(newIp)); + Promise* p = c->poolAppendPromise + (frame->addressPromise(c->machineIp(newIp))); if (i == 0) { - start = c->promiseConstant(p); + start = frame->addressOperand(p); } } assert(t, start); @@ -3854,6 +3874,17 @@ finish(MyThread* t, Allocator* allocator, Context* context) c->writeTo(start); + BootContext* bc = context->bootContext; + if (bc) { + for (DelayedPromise* p = bc->addresses; + p != bc->addressSentinal; + p = p->next) + { + p->basis = new (bc->zone->allocate(sizeof(ResolvedPromise))) + ResolvedPromise(p->basis->value()); + } + } + translateExceptionHandlerTable(t, c, methodCode(t, context->method), reinterpret_cast(start)); if (UNLIKELY(t->exception)) return 0; @@ -5063,16 +5094,18 @@ class MyProcessor: public Processor { virtual void compileMethod(Thread* vmt, Zone* zone, uint8_t* code, unsigned* offset, unsigned capacity, - object* constants, object* calls, object method) + object* constants, object* calls, + DelayedPromise** addresses, object method) { MyThread* t = static_cast(vmt); FixedAllocator allocator(t, code + *offset, capacity); - BootContext bootContext(t, *constants, *calls, zone); + BootContext bootContext(t, *constants, *calls, *addresses, zone); compile(t, &allocator, &bootContext, method); *constants = bootContext.constants; *calls = bootContext.calls; + *addresses = bootContext.addresses; *offset += allocator.offset; } @@ -5334,8 +5367,14 @@ fixupCode(Thread*, uintptr_t* map, unsigned size, uint8_t* code, if (w & (static_cast(1) << bit)) { unsigned index = indexOf(word, bit); uintptr_t v; memcpy(&v, code + index, BytesPerWord); - v = reinterpret_cast(heap + v - 1); - memcpy(code + index, &v, BytesPerWord); + uintptr_t mark = v >> BootShift; + if (mark) { + v = reinterpret_cast(code + (v & BootMask)); + memcpy(code + index, &v, BytesPerWord); + } else { + v = reinterpret_cast(heap + v - 1); + memcpy(code + index, &v, BytesPerWord); + } } } } @@ -5435,8 +5474,8 @@ boot(MyThread* t, BootImage* image) (codeMapSize(image->codeSize), BytesPerWord); uint8_t* code = reinterpret_cast(codeMap + codeMapSizeInWords); - fprintf(stderr, "code from %p to %p\n", - code, code + image->codeSize); +// fprintf(stderr, "code from %p to %p\n", +// code, code + image->codeSize); fixupHeap(t, heapMap, heapMapSizeInWords, heap); diff --git a/src/compiler.cpp b/src/compiler.cpp index 1ef9659829..7e80a91d2e 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -3060,8 +3060,26 @@ class MyCompiler: public Compiler { int i = 0; for (ConstantPoolNode* n = c.firstConstant; n; n = n->next) { - *reinterpret_cast(dst + pad(c.assembler->length()) + i) - = n->promise->value(); + intptr_t* target = reinterpret_cast + (dst + pad(c.assembler->length()) + i); + + if (n->promise->resolved()) { + *target = n->promise->value(); + } else { + class Listener: public Promise::Listener { + public: + Listener(intptr_t* target): target(target){ } + + virtual void* resolve(int64_t value) { + *target = value; + return target; + } + + intptr_t* target; + }; + new (n->promise->listen(sizeof(Listener))) Listener(target); + } + i += BytesPerWord; } } diff --git a/src/heap.cpp b/src/heap.cpp index 09f49f4bf8..bea641e8e2 100644 --- a/src/heap.cpp +++ b/src/heap.cpp @@ -1759,6 +1759,7 @@ class MyHeap: public Heap { bool targetNeedsMark(void* target) { return target and not c.gen2.contains(target) + and not immortalHeapContains(&c, target) and not (c.client->isFixed(target) and fixie(target)->age >= FixieTenureThreshold); } diff --git a/src/processor.h b/src/processor.h index b4ada313b0..94177a9abd 100644 --- a/src/processor.h +++ b/src/processor.h @@ -17,6 +17,7 @@ #include "bootimage.h" #include "heapwalk.h" #include "zone.h" +#include "assembler.h" namespace vm { @@ -122,7 +123,7 @@ class Processor { virtual void compileMethod(Thread* t, Zone* zone, uint8_t* code, unsigned* offset, unsigned capacity, object* constants, object* calls, - object method) = 0; + DelayedPromise** addresses, object method) = 0; virtual void visitRoots(BootImage* image, HeapWalker* w) = 0;