mirror of
https://github.com/corda/corda.git
synced 2025-01-07 13:38:47 +00:00
mark and fix up absolute addresses in boot image code
This commit is contained in:
parent
25ade1484a
commit
d4363d250a
@ -129,6 +129,33 @@ class ListenPromise: public Promise {
|
|||||||
System* s;
|
System* s;
|
||||||
Allocator* allocator;
|
Allocator* allocator;
|
||||||
Listener* listener;
|
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<Listener*>(allocator->allocate(sizeInBytes));
|
||||||
|
l->next = listener;
|
||||||
|
listener = l;
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
Promise* basis;
|
||||||
|
DelayedPromise* next;
|
||||||
};
|
};
|
||||||
|
|
||||||
class TraceHandler {
|
class TraceHandler {
|
||||||
|
@ -33,7 +33,7 @@ endsWith(const char* suffix, const char* s, unsigned length)
|
|||||||
|
|
||||||
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, uintptr_t* codeMap)
|
||||||
{
|
{
|
||||||
unsigned size = 0;
|
unsigned size = 0;
|
||||||
t->m->processor->compileThunks(t, image, code, &size, capacity);
|
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;
|
object calls = 0;
|
||||||
PROTECT(t, calls);
|
PROTECT(t, calls);
|
||||||
|
|
||||||
|
DelayedPromise* addresses = 0;
|
||||||
|
|
||||||
for (Finder::Iterator it(t->m->finder); it.hasMore();) {
|
for (Finder::Iterator it(t->m->finder); it.hasMore();) {
|
||||||
unsigned nameSize;
|
unsigned nameSize;
|
||||||
const char* name = it.next(&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);
|
object method = arrayBody(t, classMethodTable(t, c), i);
|
||||||
if (methodCode(t, method) or (methodFlags(t, method) & ACC_NATIVE)) {
|
if (methodCode(t, method) or (methodFlags(t, method) & ACC_NATIVE)) {
|
||||||
t->m->processor->compileMethod
|
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);
|
->listener->resolve(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (; addresses; addresses = addresses->next) {
|
||||||
|
uint8_t* value = reinterpret_cast<uint8_t*>(addresses->basis->value());
|
||||||
|
assert(t, value >= code);
|
||||||
|
|
||||||
|
void* dst = addresses->listener->resolve
|
||||||
|
((value - code) | (1 << BootShift));
|
||||||
|
assert(t, reinterpret_cast<intptr_t>(dst)
|
||||||
|
>= reinterpret_cast<intptr_t>(code));
|
||||||
|
|
||||||
|
markBit(codeMap, reinterpret_cast<intptr_t>(dst)
|
||||||
|
- reinterpret_cast<intptr_t>(code));
|
||||||
|
}
|
||||||
|
|
||||||
image->codeSize = size;
|
image->codeSize = size;
|
||||||
|
|
||||||
return constants;
|
return constants;
|
||||||
@ -250,7 +266,8 @@ writeBootImage(Thread* t, FILE* out)
|
|||||||
(t->m->heap->allocate(codeMapSize(CodeCapacity)));
|
(t->m->heap->allocate(codeMapSize(CodeCapacity)));
|
||||||
memset(codeMap, 0, 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);
|
PROTECT(t, constants);
|
||||||
|
|
||||||
const unsigned HeapCapacity = 32 * 1024 * 1024;
|
const unsigned HeapCapacity = 32 * 1024 * 1024;
|
||||||
|
@ -466,13 +466,17 @@ class BootContext {
|
|||||||
BootContext* c;
|
BootContext* c;
|
||||||
};
|
};
|
||||||
|
|
||||||
BootContext(Thread* t, object constants, object calls, Zone* zone):
|
BootContext(Thread* t, object constants, object calls,
|
||||||
protector(t, this), constants(constants), calls(calls), zone(zone)
|
DelayedPromise* addresses, Zone* zone):
|
||||||
|
protector(t, this), constants(constants), calls(calls),
|
||||||
|
addresses(addresses), addressSentinal(addresses), zone(zone)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
MyProtector protector;
|
MyProtector protector;
|
||||||
object constants;
|
object constants;
|
||||||
object calls;
|
object calls;
|
||||||
|
DelayedPromise* addresses;
|
||||||
|
DelayedPromise* addressSentinal;
|
||||||
Zone* zone;
|
Zone* zone;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -856,6 +860,21 @@ class Frame {
|
|||||||
set(sp - 2, saved);
|
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) {
|
Compiler::Operand* machineIp(unsigned logicalIp) {
|
||||||
return c->promiseConstant(c->machineIp(logicalIp));
|
return c->promiseConstant(c->machineIp(logicalIp));
|
||||||
}
|
}
|
||||||
@ -2997,7 +3016,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
|||||||
|
|
||||||
c->saveStack();
|
c->saveStack();
|
||||||
|
|
||||||
frame->pushAddress(frame->machineIp(ip));
|
frame->pushAddress(frame->addressOperand(c->machineIp(ip)));
|
||||||
c->jmp(frame->machineIp(newIp));
|
c->jmp(frame->machineIp(newIp));
|
||||||
|
|
||||||
// NB: we assume that the stack will look the same on return
|
// 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);
|
uint32_t defaultIp = base + codeReadInt32(t, code, ip);
|
||||||
assert(t, defaultIp < codeLength(t, code));
|
assert(t, defaultIp < codeLength(t, code));
|
||||||
|
|
||||||
Compiler::Operand* default_ = c->address
|
Compiler::Operand* default_ = frame->addressOperand
|
||||||
(c->poolAppendPromise(c->machineIp(defaultIp)));
|
(c->machineIp(defaultIp));
|
||||||
|
|
||||||
int32_t pairCount = codeReadInt32(t, code, ip);
|
int32_t pairCount = codeReadInt32(t, code, ip);
|
||||||
|
|
||||||
@ -3162,9 +3181,9 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
|||||||
|
|
||||||
Promise* p = c->poolAppend(key);
|
Promise* p = c->poolAppend(key);
|
||||||
if (i == 0) {
|
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);
|
assert(t, start);
|
||||||
|
|
||||||
@ -3475,9 +3494,10 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
|||||||
|
|
||||||
ipTable[i] = newIp;
|
ipTable[i] = newIp;
|
||||||
|
|
||||||
Promise* p = c->poolAppendPromise(c->machineIp(newIp));
|
Promise* p = c->poolAppendPromise
|
||||||
|
(frame->addressPromise(c->machineIp(newIp)));
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
start = c->promiseConstant(p);
|
start = frame->addressOperand(p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert(t, start);
|
assert(t, start);
|
||||||
@ -3854,6 +3874,17 @@ finish(MyThread* t, Allocator* allocator, Context* context)
|
|||||||
|
|
||||||
c->writeTo(start);
|
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),
|
translateExceptionHandlerTable(t, c, methodCode(t, context->method),
|
||||||
reinterpret_cast<intptr_t>(start));
|
reinterpret_cast<intptr_t>(start));
|
||||||
if (UNLIKELY(t->exception)) return 0;
|
if (UNLIKELY(t->exception)) return 0;
|
||||||
@ -5063,16 +5094,18 @@ class MyProcessor: public Processor {
|
|||||||
|
|
||||||
virtual void compileMethod(Thread* vmt, Zone* zone, uint8_t* code,
|
virtual void compileMethod(Thread* vmt, Zone* zone, uint8_t* code,
|
||||||
unsigned* offset, unsigned capacity,
|
unsigned* offset, unsigned capacity,
|
||||||
object* constants, object* calls, object method)
|
object* constants, object* calls,
|
||||||
|
DelayedPromise** addresses, object method)
|
||||||
{
|
{
|
||||||
MyThread* t = static_cast<MyThread*>(vmt);
|
MyThread* t = static_cast<MyThread*>(vmt);
|
||||||
FixedAllocator allocator(t, code + *offset, capacity);
|
FixedAllocator allocator(t, code + *offset, capacity);
|
||||||
BootContext bootContext(t, *constants, *calls, zone);
|
BootContext bootContext(t, *constants, *calls, *addresses, zone);
|
||||||
|
|
||||||
compile(t, &allocator, &bootContext, method);
|
compile(t, &allocator, &bootContext, method);
|
||||||
|
|
||||||
*constants = bootContext.constants;
|
*constants = bootContext.constants;
|
||||||
*calls = bootContext.calls;
|
*calls = bootContext.calls;
|
||||||
|
*addresses = bootContext.addresses;
|
||||||
*offset += allocator.offset;
|
*offset += allocator.offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5334,6 +5367,11 @@ fixupCode(Thread*, uintptr_t* map, unsigned size, uint8_t* code,
|
|||||||
if (w & (static_cast<uintptr_t>(1) << bit)) {
|
if (w & (static_cast<uintptr_t>(1) << bit)) {
|
||||||
unsigned index = indexOf(word, bit);
|
unsigned index = indexOf(word, bit);
|
||||||
uintptr_t v; memcpy(&v, code + index, BytesPerWord);
|
uintptr_t v; memcpy(&v, code + index, BytesPerWord);
|
||||||
|
uintptr_t mark = v >> BootShift;
|
||||||
|
if (mark) {
|
||||||
|
v = reinterpret_cast<uintptr_t>(code + (v & BootMask));
|
||||||
|
memcpy(code + index, &v, BytesPerWord);
|
||||||
|
} else {
|
||||||
v = reinterpret_cast<uintptr_t>(heap + v - 1);
|
v = reinterpret_cast<uintptr_t>(heap + v - 1);
|
||||||
memcpy(code + index, &v, BytesPerWord);
|
memcpy(code + index, &v, BytesPerWord);
|
||||||
}
|
}
|
||||||
@ -5341,6 +5379,7 @@ fixupCode(Thread*, uintptr_t* map, unsigned size, uint8_t* code,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
fixupMethods(Thread* t, BootImage* image, uint8_t* code)
|
fixupMethods(Thread* t, BootImage* image, uint8_t* code)
|
||||||
@ -5435,8 +5474,8 @@ boot(MyThread* t, BootImage* image)
|
|||||||
(codeMapSize(image->codeSize), BytesPerWord);
|
(codeMapSize(image->codeSize), BytesPerWord);
|
||||||
uint8_t* code = reinterpret_cast<uint8_t*>(codeMap + codeMapSizeInWords);
|
uint8_t* code = reinterpret_cast<uint8_t*>(codeMap + codeMapSizeInWords);
|
||||||
|
|
||||||
fprintf(stderr, "code from %p to %p\n",
|
// fprintf(stderr, "code from %p to %p\n",
|
||||||
code, code + image->codeSize);
|
// code, code + image->codeSize);
|
||||||
|
|
||||||
fixupHeap(t, heapMap, heapMapSizeInWords, heap);
|
fixupHeap(t, heapMap, heapMapSizeInWords, heap);
|
||||||
|
|
||||||
|
@ -3060,8 +3060,26 @@ class MyCompiler: public Compiler {
|
|||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (ConstantPoolNode* n = c.firstConstant; n; n = n->next) {
|
for (ConstantPoolNode* n = c.firstConstant; n; n = n->next) {
|
||||||
*reinterpret_cast<intptr_t*>(dst + pad(c.assembler->length()) + i)
|
intptr_t* target = reinterpret_cast<intptr_t*>
|
||||||
= n->promise->value();
|
(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;
|
i += BytesPerWord;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1759,6 +1759,7 @@ class MyHeap: public Heap {
|
|||||||
bool targetNeedsMark(void* target) {
|
bool targetNeedsMark(void* target) {
|
||||||
return target
|
return target
|
||||||
and not c.gen2.contains(target)
|
and not c.gen2.contains(target)
|
||||||
|
and not immortalHeapContains(&c, target)
|
||||||
and not (c.client->isFixed(target)
|
and not (c.client->isFixed(target)
|
||||||
and fixie(target)->age >= FixieTenureThreshold);
|
and fixie(target)->age >= FixieTenureThreshold);
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
#include "bootimage.h"
|
#include "bootimage.h"
|
||||||
#include "heapwalk.h"
|
#include "heapwalk.h"
|
||||||
#include "zone.h"
|
#include "zone.h"
|
||||||
|
#include "assembler.h"
|
||||||
|
|
||||||
namespace vm {
|
namespace vm {
|
||||||
|
|
||||||
@ -122,7 +123,7 @@ class Processor {
|
|||||||
virtual void
|
virtual void
|
||||||
compileMethod(Thread* t, Zone* zone, uint8_t* code, unsigned* offset,
|
compileMethod(Thread* t, Zone* zone, uint8_t* code, unsigned* offset,
|
||||||
unsigned capacity, object* constants, object* calls,
|
unsigned capacity, object* constants, object* calls,
|
||||||
object method) = 0;
|
DelayedPromise** addresses, object method) = 0;
|
||||||
|
|
||||||
virtual void
|
virtual void
|
||||||
visitRoots(BootImage* image, HeapWalker* w) = 0;
|
visitRoots(BootImage* image, HeapWalker* w) = 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user