diff --git a/src/assembler.h b/src/assembler.h index 8fda163ca3..7fc00a7f98 100644 --- a/src/assembler.h +++ b/src/assembler.h @@ -82,7 +82,7 @@ class Promise { public: class Listener { public: - virtual void* resolve(int64_t value) = 0; + virtual bool resolve(int64_t value, void** location) = 0; Listener* next; }; diff --git a/src/bootimage.cpp b/src/bootimage.cpp index 492a3f757c..656a56be04 100644 --- a/src/bootimage.cpp +++ b/src/bootimage.cpp @@ -97,19 +97,25 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, } static_cast(pointerValue(t, tripleSecond(t, calls))) - ->listener->resolve(address); + ->listener->resolve(address, 0); } 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) + void* location; + bool flat = addresses->listener->resolve(0, &location); + uintptr_t offset = value - code; + if (flat) { + offset |= BootFlatConstant; + } + memcpy(location, &offset, BytesPerWord); + + assert(t, reinterpret_cast(location) >= reinterpret_cast(code)); - markBit(codeMap, reinterpret_cast(dst) + markBit(codeMap, reinterpret_cast(location) - reinterpret_cast(code)); } @@ -255,12 +261,18 @@ updateConstants(Thread* t, object constants, uint8_t* code, uintptr_t* codeMap, (pointerValue(t, tripleSecond(t, constants)))->listener; pl; pl = pl->next) { - void* dst = pl->resolve(target); + void* location; + bool flat = pl->resolve(0, &location); + uintptr_t offset = target | BootHeapOffset; + if (flat) { + offset |= BootFlatConstant; + } + memcpy(location, &offset, BytesPerWord); - assert(t, reinterpret_cast(dst) + assert(t, reinterpret_cast(location) >= reinterpret_cast(code)); - markBit(codeMap, reinterpret_cast(dst) + markBit(codeMap, reinterpret_cast(location) - reinterpret_cast(code)); } } diff --git a/src/bootimage.h b/src/bootimage.h index 4b2ee7d458..90442b6d63 100644 --- a/src/bootimage.h +++ b/src/bootimage.h @@ -19,6 +19,9 @@ const unsigned BootMask = (~static_cast(0)) / BytesPerWord; const unsigned BootShift = 32 - log(BytesPerWord); +const unsigned BootFlatConstant = 1 << BootShift; +const unsigned BootHeapOffset = 1 << (BootShift + 1); + class BootImage { public: static const unsigned Magic = 0x22377322; diff --git a/src/compile.cpp b/src/compile.cpp index df17107cbd..46b77e4482 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -5639,14 +5639,19 @@ fixupCode(Thread* t, uintptr_t* map, unsigned size, uint8_t* code, for (unsigned bit = 0; bit < BitsPerWord; ++bit) { if (w & (static_cast(1) << bit)) { unsigned index = indexOf(word, bit); - uintptr_t v = arch->getConstant(code + index); - uintptr_t mark = v >> BootShift; - if (mark) { - arch->setConstant(code + index, reinterpret_cast - (code + (v & BootMask))); + uintptr_t oldValue; memcpy(&oldValue, code + index, BytesPerWord); + uintptr_t newValue; + if (oldValue & BootHeapOffset) { + newValue = reinterpret_cast + (heap + (oldValue & BootMask) - 1); } else { - arch->setConstant(code + index, reinterpret_cast - (heap + v - 1)); + newValue = reinterpret_cast + (code + (oldValue & BootMask)); + } + if (oldValue & BootFlatConstant) { + memcpy(code + index, &newValue, BytesPerWord); + } else { + arch->setConstant(code + index, newValue); } } } @@ -5766,6 +5771,8 @@ boot(MyThread* t, BootImage* image) fixupCode(t, codeMap, codeMapSizeInWords, code, heap); + syncInstructionCache(code, image->codeSize); + t->m->classMap = makeClassMap(t, classTable, image->classCount, heap); t->m->stringMap = makeStringMap(t, stringTable, image->stringCount, heap); @@ -5889,39 +5896,41 @@ compileThunks(MyThread* t, Allocator* allocator, MyProcessor* p, p->defaultThunk = finish (t, allocator, defaultContext.context.assembler, "default"); - { uint8_t* call = static_cast - (defaultContext.promise.listener->resolve - (reinterpret_cast(voidPointer(compileMethod)))); + { void* call; + defaultContext.promise.listener->resolve + (reinterpret_cast(voidPointer(compileMethod)), &call); if (image) { image->defaultThunk = p->defaultThunk - imageBase; - image->compileMethodCall = call - imageBase; + image->compileMethodCall = static_cast(call) - imageBase; } } p->nativeThunk = finish (t, allocator, nativeContext.context.assembler, "native"); - { uint8_t* call = static_cast - (nativeContext.promise.listener->resolve - (reinterpret_cast(voidPointer(invokeNative)))); + { void* call; + nativeContext.promise.listener->resolve + (reinterpret_cast(voidPointer(invokeNative)), &call); if (image) { image->nativeThunk = p->nativeThunk - imageBase; - image->invokeNativeCall = call - imageBase; + image->invokeNativeCall = static_cast(call) - imageBase; } } p->aioobThunk = finish (t, allocator, aioobContext.context.assembler, "aioob"); - { uint8_t* call = static_cast - (aioobContext.promise.listener->resolve - (reinterpret_cast(voidPointer(throwArrayIndexOutOfBounds)))); + { void* call; + aioobContext.promise.listener->resolve + (reinterpret_cast(voidPointer(throwArrayIndexOutOfBounds)), + &call); if (image) { image->aioobThunk = p->aioobThunk - imageBase; - image->throwArrayIndexOutOfBoundsCall = call - imageBase; + image->throwArrayIndexOutOfBoundsCall + = static_cast(call) - imageBase; } } @@ -5940,11 +5949,11 @@ compileThunks(MyThread* t, Allocator* allocator, MyProcessor* p, #define THUNK(s) \ tableContext.context.assembler->writeTo(start); \ start += p->thunkSize; \ - { uint8_t* call = static_cast \ - (tableContext.promise.listener->resolve \ - (reinterpret_cast(voidPointer(s)))); \ + { void* call; \ + tableContext.promise.listener->resolve \ + (reinterpret_cast(voidPointer(s)), &call); \ if (image) { \ - image->s##Call = call - imageBase; \ + image->s##Call = static_cast(call) - imageBase; \ } \ } diff --git a/src/compiler.cpp b/src/compiler.cpp index 87a646b924..c82efe1ff2 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -5288,9 +5288,10 @@ class MyCompiler: public Compiler { public: Listener(intptr_t* target): target(target){ } - virtual void* resolve(int64_t value) { + virtual bool resolve(int64_t value, void** location) { *target = value; - return target; + if (location) *location = target; + return true; } intptr_t* target; diff --git a/src/powerpc.cpp b/src/powerpc.cpp index 99e06601cb..901765115b 100644 --- a/src/powerpc.cpp +++ b/src/powerpc.cpp @@ -328,8 +328,10 @@ class OffsetListener: public Promise::Listener { conditional(conditional) { } - virtual void* resolve(int64_t value) { - return updateOffset(s, instruction, conditional, value); + virtual bool resolve(int64_t value, void** location) { + void* p = updateOffset(s, instruction, conditional, value); + if (location) *location = p; + return false; } System* s; @@ -518,8 +520,10 @@ updateImmediate(System* s, void* dst, int64_t src, unsigned size) switch (size) { case 4: { int32_t* p = static_cast(dst); - p[0] = (src >> 16) | ((~0xFFFF) & p[0]); - p[1] = (src & 0xFFFF) | ((~0xFFFF) & p[1]); + int r = (p[1] >> 21) & 31; + + p[0] = lis(r, src >> 16); + p[1] = ori(r, r, src); } break; default: abort(s); @@ -532,9 +536,10 @@ class ImmediateListener: public Promise::Listener { s(s), dst(dst), size(size), offset(offset) { } - virtual void* resolve(int64_t value) { + virtual bool resolve(int64_t value, void** location) { updateImmediate(s, dst, value, size); - return static_cast(dst) + offset; + if (location) *location = static_cast(dst) + offset; + return false; } System* s; diff --git a/src/x86.cpp b/src/x86.cpp index a5c01de2e3..50bf9efdd9 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -246,8 +246,10 @@ class OffsetListener: public Promise::Listener { instructionSize(instructionSize) { } - virtual void* resolve(int64_t value) { - return resolveOffset(s, instruction, instructionSize, value); + virtual bool resolve(int64_t value, void** location) { + void* p = resolveOffset(s, instruction, instructionSize, value); + if (location) *location = p; + return false; } System* s; @@ -314,9 +316,10 @@ class ImmediateListener: public Promise::Listener { s(s), dst(dst), size(size), offset(offset) { } - virtual void* resolve(int64_t value) { + virtual bool resolve(int64_t value, void** location) { copy(s, dst, value, size); - return static_cast(dst) + offset; + if (location) *location = static_cast(dst) + offset; + return offset == 0; } System* s;