generate read-only code image in bootimage build

This avoids the requirement of putting the code image in a
section/segment which is both writable and executable, which is good
for security and avoids trouble with systems like iOS which disallow
such things.

The implementation relies on relative addressing such that the offset
of the desired address is fixed as a compile-time constant relative to
the start of the memory area of interest (e.g. the code image, heap
image, or thunk table).  At runtime, the base pointer to the memory
area is retrieved from the thread structure and added to the offset to
compute the final address.  Using the thread pointer allows us to
generate read-only, position-independent code while avoiding the use
of IP-relative addressing, which is not available on all
architectures.
This commit is contained in:
Joel Dice 2011-09-20 16:30:30 -06:00
parent 349d381d95
commit c537dcfd34
15 changed files with 478 additions and 416 deletions

View File

@ -564,11 +564,14 @@ bootimage-generator = $(build)/bootimage-generator
bootimage-bin = $(build)/bootimage.bin
bootimage-object = $(build)/bootimage-bin.o
codeimage-bin = $(build)/codeimage.bin
codeimage-object = $(build)/codeimage-bin.o
ifeq ($(bootimage),true)
vm-classpath-object = $(bootimage-object)
cflags += -DBOOT_IMAGE=\"bootimageBin\" -DAVIAN_CLASSPATH=\"\"
vm-classpath-objects = $(bootimage-object) $(codeimage-object)
cflags += -DBOOT_IMAGE -DAVIAN_CLASSPATH=\"\"
else
vm-classpath-object = $(classpath-object)
vm-classpath-objects = $(classpath-object)
cflags += -DBOOT_CLASSPATH=\"[classpathJar]\" \
-DAVIAN_CLASSPATH=\"[classpathJar]\"
endif
@ -870,16 +873,22 @@ $(static-library): $(vm-objects) $(classpath-objects) $(vm-heapwalk-objects) \
$(ranlib) $(@)
$(bootimage-bin): $(bootimage-generator)
$(<) $(classpath-build) $(@)
$(<) $(classpath-build) $(@) $(codeimage-bin)
$(bootimage-object): $(bootimage-bin) $(converter)
@echo "creating $(@)"
$(converter) $(<) $(@) _binary_bootimage_bin_start \
_binary_bootimage_bin_end $(platform) $(arch) $(pointer-size) \
writable executable
writable
$(codeimage-object): $(bootimage-bin) $(converter)
@echo "creating $(@)"
$(converter) $(codeimage-bin) $(@) _binary_codeimage_bin_start \
_binary_codeimage_bin_end $(platform) $(arch) $(pointer-size) \
executable
executable-objects = $(vm-objects) $(classpath-objects) $(driver-object) \
$(vm-heapwalk-objects) $(boot-object) $(vm-classpath-object) \
$(vm-heapwalk-objects) $(boot-object) $(vm-classpath-objects) \
$(javahome-object) $(boot-javahome-object)
$(executable): $(executable-objects)
@ -930,7 +939,7 @@ else
endif
$(dynamic-library): $(vm-objects) $(dynamic-object) $(classpath-objects) \
$(vm-heapwalk-objects) $(boot-object) $(vm-classpath-object) \
$(vm-heapwalk-objects) $(boot-object) $(vm-classpath-objects) \
$(classpath-libraries) $(javahome-object) $(boot-javahome-object)
@echo "linking $(@)"
ifdef msvc

View File

@ -199,6 +199,24 @@ class CombinedPromise: public Promise {
Promise* high;
};
class OffsetPromise: public Promise {
public:
OffsetPromise(Promise* base, int64_t offset):
base(base), offset(offset)
{ }
virtual int64_t value() {
return base->value() + offset;
}
virtual bool resolved() {
return base->resolved();
}
Promise* base;
int64_t offset;
};
class ListenPromise: public Promise {
public:
ListenPromise(System* s, Allocator* allocator):

View File

@ -381,12 +381,14 @@ MAKE_NAME(writeElf, BITS_PER_WORD, Object)
const char* sectionName;
unsigned sectionFlags = SHF_ALLOC;
if (writable and executable) {
sectionName = ".rwx";
sectionFlags |= SHF_WRITE | SHF_EXECINSTR;
} else if (writable) {
sectionName = ".data";
sectionFlags |= SHF_WRITE;
if (writable) {
if (executable) {
sectionName = ".rwx";
sectionFlags |= SHF_WRITE | SHF_EXECINSTR;
} else {
sectionName = ".data";
sectionFlags |= SHF_WRITE;
}
} else if (executable) {
sectionName = ".text";
sectionFlags |= SHF_EXECINSTR;

View File

@ -306,7 +306,7 @@ bool
MAKE_NAME(writeMachO, BITS_PER_WORD, Object)
(uint8_t* data, unsigned size, FILE* out, const char* startName,
const char* endName, const char* architecture, unsigned alignment,
bool writable, bool)
bool writable, bool executable)
{
cpu_type_t cpuType;
cpu_subtype_t cpuSubType;
@ -330,8 +330,13 @@ MAKE_NAME(writeMachO, BITS_PER_WORD, Object)
const char* segmentName;
const char* sectionName;
if (writable) {
segmentName = "__RWX";
sectionName = "__rwx";
if (executable) {
segmentName = "__RWX";
sectionName = "__rwx";
} else {
segmentName = "__DATA";
sectionName = "__data";
}
} else {
segmentName = "__TEXT";
sectionName = "__text";

View File

@ -207,17 +207,19 @@ writePEObject
sectionMask |= IMAGE_SCN_MEM_READ;
const char* sectionName;
if (writable and executable) {
sectionName = ".rwx";
sectionMask |= IMAGE_SCN_MEM_WRITE
| IMAGE_SCN_MEM_EXECUTE
| IMAGE_SCN_CNT_CODE;
} else if (executable) {
if (writable) {
if (executable) {
sectionName = ".rwx";
sectionMask |= IMAGE_SCN_MEM_WRITE
| IMAGE_SCN_MEM_EXECUTE
| IMAGE_SCN_CNT_CODE;
} else {
sectionName = ".data";
sectionMask |= IMAGE_SCN_MEM_WRITE;
}
} else {
sectionName = ".text";
sectionMask |= IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_CNT_CODE;
} else {
sectionName = ".data";
sectionMask |= IMAGE_SCN_MEM_WRITE;
}
writeObject(data, size, out, startName, endName, sectionName, machine,

View File

@ -33,21 +33,33 @@ extern "C" void __cxa_pure_virtual(void) { abort(); }
#ifdef BOOT_IMAGE
#if (! defined __x86_64__) && ((defined __MINGW32__) || (defined _MSC_VER))
# define SYMBOL(x) binary_bootimage_bin_##x
# define BOOTIMAGE_SYMBOL(x) binary_bootimage_bin_##x
# define CODEIMAGE_SYMBOL(x) binary_codeimage_bin_##x
#else
# define SYMBOL(x) _binary_bootimage_bin_##x
# define BOOTIMAGE_SYMBOL(x) _binary_bootimage_bin_##x
# define CODEIMAGE_SYMBOL(x) _binary_codeimage_bin_##x
#endif
extern "C" {
extern const uint8_t SYMBOL(start)[];
extern const uint8_t SYMBOL(end)[];
extern const uint8_t BOOTIMAGE_SYMBOL(start)[];
extern const uint8_t BOOTIMAGE_SYMBOL(end)[];
EXPORT const uint8_t*
bootimageBin(unsigned* size)
{
*size = SYMBOL(end) - SYMBOL(start);
return SYMBOL(start);
*size = BOOTIMAGE_SYMBOL(end) - BOOTIMAGE_SYMBOL(start);
return BOOTIMAGE_SYMBOL(start);
}
extern const uint8_t CODEIMAGE_SYMBOL(start)[];
extern const uint8_t CODEIMAGE_SYMBOL(end)[];
EXPORT const uint8_t*
codeimageBin(unsigned* size)
{
*size = CODEIMAGE_SYMBOL(end) - CODEIMAGE_SYMBOL(start);
return CODEIMAGE_SYMBOL(start);
}
}

43
src/bootimage-fields.cpp Normal file
View File

@ -0,0 +1,43 @@
#ifndef FIELD
# define FIELD(name)
# define FIELD_DEFINED
#endif
FIELD(magic)
FIELD(heapSize)
FIELD(codeSize)
FIELD(bootClassCount)
FIELD(appClassCount)
FIELD(stringCount)
FIELD(callCount)
FIELD(bootLoader)
FIELD(appLoader)
FIELD(types)
FIELD(methodTree)
FIELD(methodTreeSentinal)
FIELD(virtualThunks)
#ifdef FIELD_DEFINED
# undef FIELD
# undef FIELD_DEFINED
#endif
#ifndef THUNK_FIELD
# define THUNK_FIELD(name)
# define THUNK_FIELD_DEFINED
#endif
THUNK_FIELD(default_);
THUNK_FIELD(defaultVirtual);
THUNK_FIELD(native);
THUNK_FIELD(aioob);
THUNK_FIELD(stackOverflow);
THUNK_FIELD(table);
#ifdef THUNK_FIELD_DEFINED
# undef THUNK_FIELD
# undef THUNK_FIELD_DEFINED
#endif

View File

@ -265,8 +265,8 @@ targetFieldOffset(Thread* t, object typeMaps, object field)
object
makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code,
target_uintptr_t* codeMap, const char* className,
const char* methodName, const char* methodSpec, object typeMaps)
const char* className, const char* methodName,
const char* methodSpec, object typeMaps)
{
PROTECT(t, typeMaps);
@ -671,21 +671,8 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code,
uint8_t* value = reinterpret_cast<uint8_t*>(addresses->basis->value());
expect(t, value >= code);
void* location;
bool flat = addresses->listener->resolve
(reinterpret_cast<int64_t>(code), &location);
target_uintptr_t offset = value - code;
if (flat) {
offset |= TargetBootFlatConstant;
}
offset = targetVW(offset);
memcpy(location, &offset, TargetBytesPerWord);
expect(t, reinterpret_cast<intptr_t>(location)
>= reinterpret_cast<intptr_t>(code));
targetMarkBit(codeMap, reinterpret_cast<intptr_t>(location)
- reinterpret_cast<intptr_t>(code));
addresses->listener->resolve
(targetVW(static_cast<target_intptr_t>(value - code)), 0);
}
for (; methods; methods = pairSecond(t, methods)) {
@ -1260,8 +1247,7 @@ makeHeapImage(Thread* t, BootImage* image, target_uintptr_t* heap,
}
void
updateConstants(Thread* t, object constants, uint8_t* code,
target_uintptr_t* codeMap, HeapMap* heapTable)
updateConstants(Thread* t, object constants, HeapMap* heapTable)
{
for (; constants; constants = tripleThird(t, constants)) {
unsigned target = heapTable->find(tripleFirst(t, constants));
@ -1271,26 +1257,7 @@ updateConstants(Thread* t, object constants, uint8_t* code,
(pointerValue(t, tripleSecond(t, constants)))->listener;
pl; pl = pl->next)
{
void* location;
bool flat = pl->resolve(0, &location);
target_uintptr_t offset = target | TargetBootHeapOffset;
if (flat) {
offset |= TargetBootFlatConstant;
}
offset = targetVW(offset);
memcpy(location, &offset, TargetBytesPerWord);
expect(t, reinterpret_cast<intptr_t>(location)
>= reinterpret_cast<intptr_t>(code));
// fprintf(stderr, "mark constant %d %d\n",
// static_cast<unsigned>
// (reinterpret_cast<intptr_t>(location)
// - reinterpret_cast<intptr_t>(code)),
// static_cast<unsigned>(offset));
targetMarkBit(codeMap, reinterpret_cast<intptr_t>(location)
- reinterpret_cast<intptr_t>(code));
pl->resolve((target - 1) * TargetBytesPerWord, 0);
}
}
}
@ -1309,16 +1276,12 @@ targetThunk(BootImage::Thunk t)
}
void
writeBootImage2(Thread* t, FILE* out, BootImage* image, uint8_t* code,
unsigned codeCapacity, const char* className,
writeBootImage2(Thread* t, FILE* bootimageOutput, FILE* codeOutput,
BootImage* image, uint8_t* code, const char* className,
const char* methodName, const char* methodSpec)
{
Zone zone(t->m->system, t->m->heap, 64 * 1024);
target_uintptr_t* codeMap = static_cast<target_uintptr_t*>
(t->m->heap->allocate(codeMapSize(codeCapacity)));
memset(codeMap, 0, codeMapSize(codeCapacity));
object classPoolMap;
object typeMaps;
object constants;
@ -1471,8 +1434,7 @@ writeBootImage2(Thread* t, FILE* out, BootImage* image, uint8_t* code,
}
constants = makeCodeImage
(t, &zone, image, code, codeMap, className, methodName, methodSpec,
typeMaps);
(t, &zone, image, code, className, methodName, methodSpec, typeMaps);
PROTECT(t, constants);
@ -1549,7 +1511,7 @@ writeBootImage2(Thread* t, FILE* out, BootImage* image, uint8_t* code,
HeapWalker* heapWalker = makeHeapImage
(t, image, heap, heapMap, HeapCapacity, constants, typeMaps);
updateConstants(t, constants, code, codeMap, heapWalker->map());
updateConstants(t, constants, heapWalker->map());
image->bootClassCount = hashMapSize
(t, classLoaderMap(t, root(t, Machine::BootLoader)));
@ -1618,50 +1580,53 @@ writeBootImage2(Thread* t, FILE* out, BootImage* image, uint8_t* code,
#include "bootimage-fields.cpp"
#undef THUNK_FIELD
fwrite(&targetImage, sizeof(BootImage), 1, out);
fwrite(&targetImage, sizeof(BootImage), 1, bootimageOutput);
}
fwrite(bootClassTable, image->bootClassCount * sizeof(unsigned), 1, out);
fwrite(appClassTable, image->appClassCount * sizeof(unsigned), 1, out);
fwrite(stringTable, image->stringCount * sizeof(unsigned), 1, out);
fwrite(callTable, image->callCount * sizeof(unsigned) * 2, 1, out);
fwrite(bootClassTable, image->bootClassCount * sizeof(unsigned), 1,
bootimageOutput);
fwrite(appClassTable, image->appClassCount * sizeof(unsigned), 1,
bootimageOutput);
fwrite(stringTable, image->stringCount * sizeof(unsigned), 1,
bootimageOutput);
fwrite(callTable, image->callCount * sizeof(unsigned) * 2, 1,
bootimageOutput);
unsigned offset = (image->bootClassCount * sizeof(unsigned))
unsigned offset = sizeof(BootImage)
+ (image->bootClassCount * sizeof(unsigned))
+ (image->appClassCount * sizeof(unsigned))
+ (image->stringCount * sizeof(unsigned))
+ (image->callCount * sizeof(unsigned) * 2);
while (offset % TargetBytesPerWord) {
uint8_t c = 0;
fwrite(&c, 1, 1, out);
fwrite(&c, 1, 1, bootimageOutput);
++ offset;
}
fwrite
(heapMap, pad(heapMapSize(image->heapSize), TargetBytesPerWord), 1, out);
fwrite(heapMap, pad(heapMapSize(image->heapSize), TargetBytesPerWord), 1,
bootimageOutput);
fwrite(heap, pad(image->heapSize, TargetBytesPerWord), 1, out);
fwrite(heap, pad(image->heapSize, TargetBytesPerWord), 1, bootimageOutput);
fwrite
(codeMap, pad(codeMapSize(image->codeSize), TargetBytesPerWord), 1, out);
fwrite(code, pad(image->codeSize, TargetBytesPerWord), 1, out);
fwrite(code, pad(image->codeSize, TargetBytesPerWord), 1, codeOutput);
}
}
uint64_t
writeBootImage(Thread* t, uintptr_t* arguments)
{
FILE* out = reinterpret_cast<FILE*>(arguments[0]);
BootImage* image = reinterpret_cast<BootImage*>(arguments[1]);
uint8_t* code = reinterpret_cast<uint8_t*>(arguments[2]);
unsigned codeCapacity = arguments[3];
FILE* bootimageOutput = reinterpret_cast<FILE*>(arguments[0]);
FILE* codeOutput = reinterpret_cast<FILE*>(arguments[1]);
BootImage* image = reinterpret_cast<BootImage*>(arguments[2]);
uint8_t* code = reinterpret_cast<uint8_t*>(arguments[3]);
const char* className = reinterpret_cast<const char*>(arguments[4]);
const char* methodName = reinterpret_cast<const char*>(arguments[5]);
const char* methodSpec = reinterpret_cast<const char*>(arguments[6]);
writeBootImage2
(t, out, image, code, codeCapacity, className, methodName, methodSpec);
(t, bootimageOutput, codeOutput, image, code, className, methodName,
methodSpec);
return 1;
}
@ -1671,8 +1636,8 @@ writeBootImage(Thread* t, uintptr_t* arguments)
int
main(int ac, const char** av)
{
if (ac < 3 or ac > 6) {
fprintf(stderr, "usage: %s <classpath> <output file> "
if (ac < 4 or ac > 7) {
fprintf(stderr, "usage: %s <classpath> <bootimage file> <code file>"
"[<class name> [<method name> [<method spec>]]]\n", av[0]);
return -1;
}
@ -1701,23 +1666,30 @@ main(int ac, const char** av)
enter(t, Thread::ActiveState);
enter(t, Thread::IdleState);
FILE* output = vm::fopen(av[2], "wb");
if (output == 0) {
FILE* bootimageOutput = vm::fopen(av[2], "wb");
if (bootimageOutput == 0) {
fprintf(stderr, "unable to open %s\n", av[2]);
return -1;
}
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(output),
FILE* codeOutput = vm::fopen(av[3], "wb");
if (codeOutput == 0) {
fprintf(stderr, "unable to open %s\n", av[3]);
return -1;
}
uintptr_t arguments[] = { reinterpret_cast<uintptr_t>(bootimageOutput),
reinterpret_cast<uintptr_t>(codeOutput),
reinterpret_cast<uintptr_t>(&image),
reinterpret_cast<uintptr_t>(code),
CodeCapacity,
reinterpret_cast<uintptr_t>(ac > 3 ? av[3] : 0),
reinterpret_cast<uintptr_t>(ac > 4 ? av[4] : 0),
reinterpret_cast<uintptr_t>(ac > 5 ? av[5] : 0) };
reinterpret_cast<uintptr_t>(ac > 5 ? av[5] : 0),
reinterpret_cast<uintptr_t>(ac > 6 ? av[6] : 0) };
run(t, writeBootImage, arguments);
fclose(output);
fclose(codeOutput);
fclose(bootimageOutput);
if (t->exception) {
printTrace(t, t->exception);

View File

@ -71,6 +71,20 @@ enum Root {
RewindMethod
};
enum ThunkIndex {
compileMethodIndex,
compileVirtualMethodIndex,
invokeNativeIndex,
throwArrayIndexOutOfBoundsIndex,
throwStackOverflowIndex,
#define THUNK(s) s##Index,
#include "thunks.cpp"
#undef THUNK
dummyIndex
};
const unsigned RootCount = RewindMethod + 1;
inline bool
@ -229,6 +243,9 @@ class MyThread: public Thread {
tailAddress(0),
virtualCallTarget(0),
virtualCallIndex(0),
heapImage(0),
codeImage(0),
thunkTable(0),
trace(0),
reference(0),
arch(parent
@ -252,6 +269,9 @@ class MyThread: public Thread {
void* tailAddress;
void* virtualCallTarget;
uintptr_t virtualCallIndex;
uintptr_t* heapImage;
uint8_t* codeImage;
void** thunkTable;
CallTrace* trace;
Reference* reference;
Assembler::Architecture* arch;
@ -1310,6 +1330,9 @@ storeLocal(Context* context, unsigned footprint, Compiler::Operand* value,
(footprint, value, translateLocalIndex(context, footprint, index));
}
FixedAllocator*
codeAllocator(MyThread* t);
class Frame {
public:
enum StackType {
@ -1356,9 +1379,8 @@ class Frame {
}
Compiler::Operand* append(object o) {
if (context->bootContext) {
BootContext* bc = context->bootContext;
BootContext* bc = context->bootContext;
if (bc) {
Promise* p = new (bc->zone->allocate(sizeof(ListenPromise)))
ListenPromise(t->m->system, bc->zone);
@ -1366,7 +1388,11 @@ class Frame {
object pointer = makePointer(t, p);
bc->constants = makeTriple(t, o, pointer, bc->constants);
return c->promiseConstant(p, Compiler::ObjectType);
return c->add
(TargetBytesPerWord, c->memory
(c->register_(t->arch->thread()), Compiler::AddressType,
TargetThreadHeapImage), c->promiseConstant
(p, Compiler::AddressType));
} else {
for (PoolElement* e = context->objectPool; e; e = e->next) {
if (o == e->target) {
@ -1590,7 +1616,20 @@ class Frame {
}
Compiler::Operand* addressOperand(Promise* p) {
return c->promiseConstant(addressPromise(p), Compiler::AddressType);
return c->promiseConstant(p, Compiler::AddressType);
}
Compiler::Operand* absoluteAddressOperand(Promise* p) {
return context->bootContext
? c->add
(TargetBytesPerWord, c->memory
(c->register_(t->arch->thread()), Compiler::AddressType,
TargetThreadCodeImage), c->promiseConstant
(new (context->zone.allocate(sizeof(OffsetPromise)))
OffsetPromise
(p, - reinterpret_cast<intptr_t>(codeAllocator(t)->base)),
Compiler::AddressType))
: addressOperand(p);
}
Compiler::Operand* machineIp(unsigned logicalIp) {
@ -1865,7 +1904,7 @@ class Frame {
}
unsigned startSubroutine(unsigned ip, Promise* returnAddress) {
pushAddress(addressOperand(returnAddress));
pushAddress(absoluteAddressOperand(returnAddress));
Subroutine* subroutine = 0;
for (Subroutine* s = context->subroutines; s; s = s->listNext) {
@ -2247,9 +2286,6 @@ tryInitClass(MyThread* t, object class_)
initClass(t, class_);
}
FixedAllocator*
codeAllocator(MyThread* t);
void
compile(MyThread* t, FixedAllocator* allocator, BootContext* bootContext,
object method);
@ -3288,7 +3324,9 @@ compileDirectInvoke(MyThread* t, Frame* frame, object target, bool tailCall,
if (useThunk
or (TailCalls and tailCall and (methodFlags(t, target) & ACC_NATIVE)))
{
flags |= Compiler::Aligned;
if (frame->context->bootContext == 0) {
flags |= Compiler::Aligned;
}
if (TailCalls and tailCall) {
traceFlags |= TraceElement::TailCall;
@ -3308,7 +3346,8 @@ compileDirectInvoke(MyThread* t, Frame* frame, object target, bool tailCall,
methodParameterFootprint(t, target));
c->store
(TargetBytesPerWord, frame->addressOperand(returnAddressPromise),
(TargetBytesPerWord,
frame->absoluteAddressOperand(returnAddressPromise),
TargetBytesPerWord, c->memory
(c->register_(t->arch->thread()), Compiler::AddressType,
TargetThreadTailAddress));
@ -5327,12 +5366,12 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
assert(t, defaultIp < codeLength(t, code));
Compiler::Operand* default_ = frame->addressOperand
(c->machineIp(defaultIp));
(frame->addressPromise(c->machineIp(defaultIp)));
int32_t pairCount = codeReadInt32(t, code, ip);
if (pairCount) {
Compiler::Operand* start = 0;
Promise* start = 0;
THREAD_RUNTIME_ARRAY(t, uint32_t, ipTable, pairCount);
for (int32_t i = 0; i < pairCount; ++i) {
unsigned index = ip + (i * 8);
@ -5344,19 +5383,25 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
Promise* p = c->poolAppend(key);
if (i == 0) {
start = frame->addressOperand(p);
start = p;
}
c->poolAppendPromise(frame->addressPromise(c->machineIp(newIp)));
c->poolAppendPromise
(frame->addressPromise(c->machineIp(newIp)));
}
assert(t, start);
Compiler::Operand* address = c->call
(c->constant(getThunk(t, lookUpAddressThunk), Compiler::AddressType),
0, 0, TargetBytesPerWord, Compiler::AddressType,
4, key, frame->absoluteAddressOperand(start),
c->constant(pairCount, Compiler::IntegerType), default_);
c->jmp
(c->call
(c->constant
(getThunk(t, lookUpAddressThunk), Compiler::AddressType),
0, 0, TargetBytesPerWord, Compiler::AddressType,
4, key, start, c->constant(pairCount, Compiler::IntegerType),
default_));
(context->bootContext ? c->add
(TargetBytesPerWord, c->memory
(c->register_(t->arch->thread()), Compiler::AddressType,
TargetThreadCodeImage), address)
: address);
Compiler::State* state = c->saveState();
@ -5855,7 +5900,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
int32_t bottom = codeReadInt32(t, code, ip);
int32_t top = codeReadInt32(t, code, ip);
Compiler::Operand* start = 0;
Promise* start = 0;
THREAD_RUNTIME_ARRAY(t, uint32_t, ipTable, top - bottom + 1);
for (int32_t i = 0; i < top - bottom + 1; ++i) {
unsigned index = ip + (i * 4);
@ -5867,7 +5912,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
Promise* p = c->poolAppendPromise
(frame->addressPromise(c->machineIp(newIp)));
if (i == 0) {
start = frame->addressOperand(p);
start = p;
}
}
assert(t, start);
@ -5892,10 +5937,18 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
= (bottom
? c->sub(4, c->constant(bottom, Compiler::IntegerType), key) : key);
Compiler::Operand* entry = c->memory
(frame->absoluteAddressOperand(start), Compiler::AddressType, 0,
normalizedKey, TargetBytesPerWord);
c->jmp
(c->load
(TargetBytesPerWord, TargetBytesPerWord, c->memory
(start, Compiler::AddressType, 0, normalizedKey, TargetBytesPerWord),
(TargetBytesPerWord, TargetBytesPerWord, context->bootContext
? c->add
(TargetBytesPerWord, c->memory
(c->register_(t->arch->thread()), Compiler::AddressType,
TargetThreadCodeImage), entry)
: entry,
TargetBytesPerWord));
Compiler::State* state = c->saveState();
@ -7105,47 +7158,7 @@ updateCall(MyThread* t, UnaryOperation op, void* returnAddress, void* target)
}
void*
compileMethod2(MyThread* t, void* ip)
{
object node = findCallNode(t, ip);
object target = callNodeTarget(t, node);
PROTECT(t, node);
PROTECT(t, target);
t->trace->targetMethod = target;
THREAD_RESOURCE0(t, static_cast<MyThread*>(t)->trace->targetMethod = 0);
compile(t, codeAllocator(t), 0, target);
uintptr_t address;
if ((methodFlags(t, target) & ACC_NATIVE)
and useLongJump(t, reinterpret_cast<uintptr_t>(ip)))
{
address = bootNativeThunk(t);
} else {
address = methodAddress(t, target);
}
uint8_t* updateIp = static_cast<uint8_t*>(ip);
UnaryOperation op;
if (callNodeFlags(t, node) & TraceElement::LongCall) {
if (callNodeFlags(t, node) & TraceElement::TailCall) {
op = AlignedLongJump;
} else {
op = AlignedLongCall;
}
} else if (callNodeFlags(t, node) & TraceElement::TailCall) {
op = AlignedJump;
} else {
op = AlignedCall;
}
updateCall(t, op, updateIp, reinterpret_cast<void*>(address));
return reinterpret_cast<void*>(address);
}
compileMethod2(MyThread* t, void* ip);
uint64_t
compileMethod(MyThread* t)
@ -8270,7 +8283,7 @@ bool
isThunkUnsafeStack(MyThread* t, void* ip);
void
boot(MyThread* t, BootImage* image);
boot(MyThread* t, BootImage* image, uint8_t* code);
class MyProcessor;
@ -8278,7 +8291,7 @@ MyProcessor*
processor(MyThread* t);
void
compileThunks(MyThread* t, Allocator* allocator, MyProcessor* p);
compileThunks(MyThread* t, Allocator* allocator);
class MyProcessor: public Processor {
public:
@ -8312,6 +8325,9 @@ class MyProcessor: public Processor {
allocator(allocator),
roots(0),
bootImage(0),
heapImage(0),
codeImage(0),
codeImageSize(0),
segFaultHandler(Machine::NullPointerExceptionType,
Machine::NullPointerException,
FixedSizeOfNullPointerException),
@ -8321,7 +8337,18 @@ class MyProcessor: public Processor {
codeAllocator(s, 0, 0),
callTableSize(0),
useNativeFeatures(useNativeFeatures)
{ }
{
thunkTable[compileMethodIndex] = voidPointer(local::compileMethod);
thunkTable[compileVirtualMethodIndex] = voidPointer(compileVirtualMethod);
thunkTable[invokeNativeIndex] = voidPointer(invokeNative);
thunkTable[throwArrayIndexOutOfBoundsIndex] = voidPointer
(throwArrayIndexOutOfBounds);
thunkTable[throwStackOverflowIndex] = voidPointer(throwStackOverflow);
#define THUNK(s) thunkTable[s##Index] = voidPointer(s);
#include "thunks.cpp"
#undef THUNK
thunkTable[dummyIndex] = 0;
}
virtual Thread*
makeThread(Machine* m, object javaThread, Thread* parent)
@ -8329,7 +8356,10 @@ class MyProcessor: public Processor {
MyThread* t = new (m->heap->allocate(sizeof(MyThread)))
MyThread(m, javaThread, static_cast<MyThread*>(parent),
useNativeFeatures);
t->init();
t->heapImage = heapImage;
t->codeImage = codeImage;
t->thunkTable = thunkTable;
if (false) {
fprintf(stderr, "stack %d\n",
@ -8359,6 +8389,8 @@ class MyProcessor: public Processor {
exit(0);
}
t->init();
return t;
}
@ -8755,15 +8787,15 @@ class MyProcessor: public Processor {
return table;
}
virtual void boot(Thread* t, BootImage* image) {
virtual void boot(Thread* t, BootImage* image, uint8_t* code) {
if (codeAllocator.base == 0) {
codeAllocator.base = static_cast<uint8_t*>
(s->tryAllocateExecutable(ExecutableAreaSizeInBytes));
codeAllocator.capacity = ExecutableAreaSizeInBytes;
}
if (image) {
local::boot(static_cast<MyThread*>(t), image);
if (image and code) {
local::boot(static_cast<MyThread*>(t), image, code);
} else {
roots = makeArray(t, RootCount);
@ -8777,7 +8809,7 @@ class MyProcessor: public Processor {
root(t, MethodTreeSentinal));
}
local::compileThunks(static_cast<MyThread*>(t), &codeAllocator, this);
local::compileThunks(static_cast<MyThread*>(t), &codeAllocator);
segFaultHandler.m = t->m;
expect(t, t->m->system->success
@ -8840,6 +8872,9 @@ class MyProcessor: public Processor {
Allocator* allocator;
object roots;
BootImage* bootImage;
uintptr_t* heapImage;
uint8_t* codeImage;
unsigned codeImageSize;
SignalHandler segFaultHandler;
SignalHandler divideByZeroHandler;
FixedAllocator codeAllocator;
@ -8847,8 +8882,57 @@ class MyProcessor: public Processor {
ThunkCollection bootThunks;
unsigned callTableSize;
bool useNativeFeatures;
void* thunkTable[dummyIndex + 1];
};
void*
compileMethod2(MyThread* t, void* ip)
{
object node = findCallNode(t, ip);
object target = callNodeTarget(t, node);
PROTECT(t, node);
PROTECT(t, target);
t->trace->targetMethod = target;
THREAD_RESOURCE0(t, static_cast<MyThread*>(t)->trace->targetMethod = 0);
compile(t, codeAllocator(t), 0, target);
uintptr_t address;
if ((methodFlags(t, target) & ACC_NATIVE)
and useLongJump(t, reinterpret_cast<uintptr_t>(ip)))
{
address = bootNativeThunk(t);
} else {
address = methodAddress(t, target);
}
uint8_t* updateIp = static_cast<uint8_t*>(ip);
MyProcessor* p = processor(t);
if (updateIp < p->codeImage or updateIp >= p->codeImage + p->codeImageSize) {
UnaryOperation op;
if (callNodeFlags(t, node) & TraceElement::LongCall) {
if (callNodeFlags(t, node) & TraceElement::TailCall) {
op = AlignedLongJump;
} else {
op = AlignedLongCall;
}
} else if (callNodeFlags(t, node) & TraceElement::TailCall) {
op = AlignedJump;
} else {
op = AlignedCall;
}
updateCall(t, op, updateIp, reinterpret_cast<void*>(address));
}
return reinterpret_cast<void*>(address);
}
bool
isThunk(MyProcessor::ThunkCollection* thunks, void* ip)
{
@ -9132,45 +9216,6 @@ fixupHeap(MyThread* t UNUSED, uintptr_t* map, unsigned size, uintptr_t* heap)
}
}
void
fixupCode(Thread* t, uintptr_t* map, unsigned size, uint8_t* code,
uintptr_t* heap)
{
Assembler::Architecture* arch = makeArchitecture(t->m->system, false);
arch->acquire();
for (unsigned word = 0; word < size; ++word) {
uintptr_t w = map[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 oldValue; memcpy(&oldValue, code + index, BytesPerWord);
uintptr_t newValue;
if (oldValue & BootHeapOffset) {
newValue = reinterpret_cast<uintptr_t>
(heap + (oldValue & BootMask) - 1);
// fprintf(stderr, "constant marked %d %d\n",
// index, static_cast<unsigned>(oldValue));
} else {
newValue = reinterpret_cast<uintptr_t>
(code + (oldValue & BootMask));
}
if (oldValue & BootFlatConstant) {
memcpy(code + index, &newValue, BytesPerWord);
} else {
arch->setConstant(code + index, newValue);
}
}
}
}
}
arch->release();
}
void
fixupMethods(Thread* t, object map, BootImage* image UNUSED, uint8_t* code)
{
@ -9216,7 +9261,7 @@ thunkToThunk(const BootImage::Thunk& thunk, uint8_t* base)
}
void
fixupThunks(MyThread* t, BootImage* image, uint8_t* code)
findThunks(MyThread* t, BootImage* image, uint8_t* code)
{
MyProcessor* p = processor(t);
@ -9228,28 +9273,6 @@ fixupThunks(MyThread* t, BootImage* image, uint8_t* code)
p->bootThunks.stackOverflow
= thunkToThunk(image->thunks.stackOverflow, code);
p->bootThunks.table = thunkToThunk(image->thunks.table, code);
updateCall(t, LongCall, code + image->compileMethodCall,
voidPointer(local::compileMethod));
updateCall(t, LongCall, code + image->compileVirtualMethodCall,
voidPointer(local::compileVirtualMethod));
updateCall(t, LongCall, code + image->invokeNativeCall,
voidPointer(invokeNative));
updateCall(t, LongCall, code + image->throwArrayIndexOutOfBoundsCall,
voidPointer(throwArrayIndexOutOfBounds));
updateCall(t, LongCall, code + image->throwStackOverflowCall,
voidPointer(throwStackOverflow));
#define THUNK(s) \
updateCall(t, LongJump, code + image->s##Call, voidPointer(s));
#include "thunks.cpp"
#undef THUNK
}
void
@ -9266,7 +9289,7 @@ fixupVirtualThunks(MyThread* t, uint8_t* code)
}
void
boot(MyThread* t, BootImage* image)
boot(MyThread* t, BootImage* image, uint8_t* code)
{
assert(t, image->magic == BootImage::Magic);
@ -9277,17 +9300,20 @@ boot(MyThread* t, BootImage* image)
uintptr_t* heapMap = reinterpret_cast<uintptr_t*>
(padWord(reinterpret_cast<uintptr_t>(callTable + (image->callCount * 2))));
unsigned heapMapSizeInWords = ceiling
(heapMapSize(image->heapSize), BytesPerWord);
uintptr_t* heap = heapMap + heapMapSizeInWords;
MyProcessor* p = static_cast<MyProcessor*>(t->m->processor);
t->heapImage = p->heapImage = heap;
// fprintf(stderr, "heap from %p to %p\n",
// heap, heap + ceiling(image->heapSize, BytesPerWord));
uintptr_t* codeMap = heap + ceiling(image->heapSize, BytesPerWord);
unsigned codeMapSizeInWords = ceiling
(codeMapSize(image->codeSize), BytesPerWord);
uint8_t* code = reinterpret_cast<uint8_t*>(codeMap + codeMapSizeInWords);
t->codeImage = p->codeImage = code;
p->codeImageSize = image->codeSize;
// fprintf(stderr, "code from %p to %p\n",
// code, code + image->codeSize);
@ -9303,8 +9329,6 @@ boot(MyThread* t, BootImage* image)
setRoot(t, Machine::BootLoader, bootObject(heap, image->bootLoader));
setRoot(t, Machine::AppLoader, bootObject(heap, image->appLoader));
MyProcessor* p = static_cast<MyProcessor*>(t->m->processor);
p->roots = makeArray(t, RootCount);
setRoot(t, MethodTree, bootObject(heap, image->methodTree));
@ -9312,8 +9336,6 @@ boot(MyThread* t, BootImage* image)
setRoot(t, VirtualThunks, bootObject(heap, image->virtualThunks));
fixupCode(t, codeMap, codeMapSizeInWords, code, heap);
syncInstructionCache(code, image->codeSize);
{ object map = makeClassMap(t, bootClassTable, image->bootClassCount, heap);
@ -9341,7 +9363,7 @@ boot(MyThread* t, BootImage* image)
(t, bootClassTable, image->bootClassCount,
appClassTable, image->appClassCount, heap));
fixupThunks(t, image, code);
findThunks(t, image, code);
fixupVirtualThunks(t, code);
@ -9369,23 +9391,37 @@ thunkToThunk(const MyProcessor::Thunk& thunk, uint8_t* base)
}
void
compileThunks(MyThread* t, Allocator* allocator, MyProcessor* p)
compileCall(MyThread* t, Context* c, ThunkIndex index, bool call = true)
{
class ThunkContext {
public:
ThunkContext(MyThread* t, Zone* zone):
context(t), promise(t->m->system, zone)
{ }
Assembler* a = c->assembler;
Context context;
ListenPromise promise;
};
if (processor(t)->bootImage) {
Assembler::Memory table(t->arch->thread(), TargetThreadThunkTable);
// use Architecture::virtualCallTarget register here as a scratch
// register; any register that isn't used to pass arguments would
// be acceptable:
Assembler::Register tableRegister(t->arch->virtualCallTarget());
a->apply(Move, TargetBytesPerWord, MemoryOperand, &table,
TargetBytesPerWord, RegisterOperand, &tableRegister);
Assembler::Memory proc(tableRegister.low, index * TargetBytesPerWord);
a->apply(call ? Call : Jump, TargetBytesPerWord, MemoryOperand, &proc);
} else {
Assembler::Constant proc
(new (c->zone.allocate(sizeof(ResolvedPromise)))
ResolvedPromise(reinterpret_cast<intptr_t>(t->thunkTable[index])));
Zone zone(t->m->system, t->m->heap, 1024);
a->apply
(call ? LongCall : LongJump, TargetBytesPerWord, ConstantOperand, &proc);
}
}
ThunkContext defaultContext(t, &zone);
void
compileThunks(MyThread* t, Allocator* allocator)
{
MyProcessor* p = processor(t);
{ Assembler* a = defaultContext.context.assembler;
{ Context context(t);
Assembler* a = context.assembler;
a->saveFrame(TargetThreadStack, TargetThreadIp);
@ -9394,8 +9430,7 @@ compileThunks(MyThread* t, Allocator* allocator, MyProcessor* p)
Assembler::Register thread(t->arch->thread());
a->pushFrame(1, TargetBytesPerWord, RegisterOperand, &thread);
Assembler::Constant proc(&(defaultContext.promise));
a->apply(LongCall, TargetBytesPerWord, ConstantOperand, &proc);
compileCall(t, &context, compileMethodIndex);
a->popFrame(t->arch->alignFrameSize(1));
@ -9403,12 +9438,14 @@ compileThunks(MyThread* t, Allocator* allocator, MyProcessor* p)
a->apply(Jump, TargetBytesPerWord, RegisterOperand, &result);
p->thunks.default_.length = a->endBlock(false)->resolve(0, 0);
p->thunks.default_.start = finish
(t, allocator, a, "default", p->thunks.default_.length);
}
ThunkContext defaultVirtualContext(t, &zone);
{ Assembler* a = defaultVirtualContext.context.assembler;
{ Context context(t);
Assembler* a = context.assembler;
Assembler::Register class_(t->arch->virtualCallTarget());
Assembler::Memory virtualCallTargetSrc
(t->arch->stack(),
@ -9437,21 +9474,22 @@ compileThunks(MyThread* t, Allocator* allocator, MyProcessor* p)
Assembler::Register thread(t->arch->thread());
a->pushFrame(1, TargetBytesPerWord, RegisterOperand, &thread);
Assembler::Constant proc(&(defaultVirtualContext.promise));
a->apply(LongCall, TargetBytesPerWord, ConstantOperand, &proc);
compileCall(t, &context, compileVirtualMethodIndex);
a->popFrame(t->arch->alignFrameSize(1));
Assembler::Register result(t->arch->returnLow());
a->apply(Jump, TargetBytesPerWord, RegisterOperand, &result);
p->thunks.defaultVirtual.length = a->endBlock(false)->resolve(0, 0);
p->thunks.defaultVirtual.start = finish
(t, allocator, a, "defaultVirtual", p->thunks.defaultVirtual.length);
}
ThunkContext nativeContext(t, &zone);
{ Assembler* a = nativeContext.context.assembler;
{ Context context(t);
Assembler* a = context.assembler;
a->saveFrame(TargetThreadStack, TargetThreadIp);
@ -9460,19 +9498,20 @@ compileThunks(MyThread* t, Allocator* allocator, MyProcessor* p)
Assembler::Register thread(t->arch->thread());
a->pushFrame(1, TargetBytesPerWord, RegisterOperand, &thread);
Assembler::Constant proc(&(nativeContext.promise));
a->apply(LongCall, TargetBytesPerWord, ConstantOperand, &proc);
compileCall(t, &context, invokeNativeIndex);
a->popFrameAndUpdateStackAndReturn
(t->arch->alignFrameSize(1), TargetThreadStack);
p->thunks.native.length = a->endBlock(false)->resolve(0, 0);
p->thunks.native.start = finish
(t, allocator, a, "native", p->thunks.native.length);
}
ThunkContext aioobContext(t, &zone);
{ Context context(t);
Assembler* a = context.assembler;
{ Assembler* a = aioobContext.context.assembler;
a->saveFrame(TargetThreadStack, TargetThreadIp);
p->thunks.aioob.frameSavedOffset = a->length();
@ -9480,15 +9519,16 @@ compileThunks(MyThread* t, Allocator* allocator, MyProcessor* p)
Assembler::Register thread(t->arch->thread());
a->pushFrame(1, TargetBytesPerWord, RegisterOperand, &thread);
Assembler::Constant proc(&(aioobContext.promise));
a->apply(LongCall, TargetBytesPerWord, ConstantOperand, &proc);
compileCall(t, &context, throwArrayIndexOutOfBoundsIndex);
p->thunks.aioob.length = a->endBlock(false)->resolve(0, 0);
p->thunks.aioob.start = finish
(t, allocator, a, "aioob", p->thunks.aioob.length);
}
ThunkContext stackOverflowContext(t, &zone);
{ Assembler* a = stackOverflowContext.context.assembler;
{ Context context(t);
Assembler* a = context.assembler;
a->saveFrame(TargetThreadStack, TargetThreadIp);
@ -9497,133 +9537,69 @@ compileThunks(MyThread* t, Allocator* allocator, MyProcessor* p)
Assembler::Register thread(t->arch->thread());
a->pushFrame(1, TargetBytesPerWord, RegisterOperand, &thread);
Assembler::Constant proc(&(stackOverflowContext.promise));
a->apply(LongCall, TargetBytesPerWord, ConstantOperand, &proc);
compileCall(t, &context, throwStackOverflowIndex);
p->thunks.stackOverflow.length = a->endBlock(false)->resolve(0, 0);
p->thunks.stackOverflow.start = finish
(t, allocator, a, "stackOverflow", p->thunks.stackOverflow.length);
}
ThunkContext tableContext(t, &zone);
{ { Context context(t);
Assembler* a = context.assembler;
{ Assembler* a = tableContext.context.assembler;
a->saveFrame(TargetThreadStack, TargetThreadIp);
a->saveFrame(TargetThreadStack, TargetThreadIp);
p->thunks.table.frameSavedOffset = a->length();
p->thunks.table.frameSavedOffset = a->length();
Assembler::Constant proc(&(tableContext.promise));
a->apply(LongJump, TargetBytesPerWord, ConstantOperand, &proc);
compileCall(t, &context, dummyIndex, false);
p->thunks.table.length = a->endBlock(false)->resolve(0, 0);
}
p->thunks.table.length = a->endBlock(false)->resolve(0, 0);
p->thunks.default_.start = finish
(t, allocator, defaultContext.context.assembler, "default",
p->thunks.default_.length);
p->thunks.table.start = static_cast<uint8_t*>
(allocator->allocate(p->thunks.table.length * ThunkCount));
}
uint8_t* start = p->thunks.table.start;
#define THUNK(s) { \
Context context(t); \
Assembler* a = context.assembler; \
\
a->saveFrame(TargetThreadStack, TargetThreadIp); \
\
p->thunks.table.frameSavedOffset = a->length(); \
\
compileCall(t, &context, s##Index, false); \
\
expect(t, a->endBlock(false)->resolve(0, 0) \
<= p->thunks.table.length); \
\
a->setDestination(start); \
a->write(); \
\
logCompile(t, start, p->thunks.table.length, 0, #s, 0); \
\
start += p->thunks.table.length; \
}
#include "thunks.cpp"
#undef THUNK
}
BootImage* image = p->bootImage;
uint8_t* imageBase = p->codeAllocator.base;
{ void* call;
defaultContext.promise.listener->resolve
(reinterpret_cast<intptr_t>(voidPointer(compileMethod)), &call);
if (image) {
image->compileMethodCall = static_cast<uint8_t*>(call) - imageBase;
}
}
p->thunks.defaultVirtual.start = finish
(t, allocator, defaultVirtualContext.context.assembler, "defaultVirtual",
p->thunks.defaultVirtual.length);
{ void* call;
defaultVirtualContext.promise.listener->resolve
(reinterpret_cast<intptr_t>(voidPointer(compileVirtualMethod)), &call);
if (image) {
image->compileVirtualMethodCall
= static_cast<uint8_t*>(call) - imageBase;
}
}
p->thunks.native.start = finish
(t, allocator, nativeContext.context.assembler, "native",
p->thunks.native.length);
{ void* call;
nativeContext.promise.listener->resolve
(reinterpret_cast<intptr_t>(voidPointer(invokeNative)), &call);
if (image) {
image->invokeNativeCall = static_cast<uint8_t*>(call) - imageBase;
}
}
p->thunks.aioob.start = finish
(t, allocator, aioobContext.context.assembler, "aioob",
p->thunks.aioob.length);
{ void* call;
aioobContext.promise.listener->resolve
(reinterpret_cast<intptr_t>(voidPointer(throwArrayIndexOutOfBounds)),
&call);
if (image) {
image->throwArrayIndexOutOfBoundsCall
= static_cast<uint8_t*>(call) - imageBase;
}
}
p->thunks.stackOverflow.start = finish
(t, allocator, stackOverflowContext.context.assembler, "stackOverflow",
p->thunks.stackOverflow.length);
{ void* call;
stackOverflowContext.promise.listener->resolve
(reinterpret_cast<intptr_t>(voidPointer(throwStackOverflow)),
&call);
if (image) {
image->throwStackOverflowCall
= static_cast<uint8_t*>(call) - imageBase;
}
}
p->thunks.table.start = static_cast<uint8_t*>
(allocator->allocate(p->thunks.table.length * ThunkCount));
if (image) {
uint8_t* imageBase = p->codeAllocator.base;
image->thunks.default_ = thunkToThunk(p->thunks.default_, imageBase);
image->thunks.defaultVirtual
= thunkToThunk(p->thunks.defaultVirtual, imageBase);
image->thunks.defaultVirtual = thunkToThunk
(p->thunks.defaultVirtual, imageBase);
image->thunks.native = thunkToThunk(p->thunks.native, imageBase);
image->thunks.aioob = thunkToThunk(p->thunks.aioob, imageBase);
image->thunks.stackOverflow
= thunkToThunk(p->thunks.stackOverflow, imageBase);
image->thunks.stackOverflow = thunkToThunk
(p->thunks.stackOverflow, imageBase);
image->thunks.table = thunkToThunk(p->thunks.table, imageBase);
}
logCompile(t, p->thunks.table.start, p->thunks.table.length * ThunkCount, 0,
"thunkTable", 0);
uint8_t* start = p->thunks.table.start;
#define THUNK(s) \
tableContext.context.assembler->setDestination(start); \
tableContext.context.assembler->write(); \
start += p->thunks.table.length; \
{ void* call; \
tableContext.promise.listener->resolve \
(reinterpret_cast<intptr_t>(voidPointer(s)), &call); \
if (image) { \
image->s##Call = static_cast<uint8_t*>(call) - imageBase; \
} \
}
#include "thunks.cpp"
#undef THUNK
}
MyProcessor*

View File

@ -3083,8 +3083,8 @@ class MyProcessor: public Processor {
abort(s);
}
virtual void boot(vm::Thread*, BootImage* image) {
expect(s, image == 0);
virtual void boot(vm::Thread*, BootImage* image, uint8_t* code) {
expect(s, image == 0 and code == 0);
}

View File

@ -2208,7 +2208,7 @@ boot(Thread* t)
setRoot(t, Machine::StringMap, makeWeakHashMap(t, 0, 0));
m->processor->boot(t, 0);
m->processor->boot(t, 0, 0);
{ object bootCode = makeCode(t, 0, 0, 0, 0, 0, 0, 1);
codeBody(t, bootCode, 0) = impdep1;
@ -2537,15 +2537,27 @@ Thread::init()
}
BootImage* image = 0;
uint8_t* code = 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);
void* imagep = m->libraries->resolve(imageFunctionName);
if (imagep) {
BootImage* (*imageFunction)(unsigned*);
memcpy(&imageFunction, &imagep, BytesPerWord);
unsigned size;
image = function(&size);
image = imageFunction(&size);
const char* codeFunctionName = findProperty(m, "avian.codeimage");
if (codeFunctionName) {
void* codep = m->libraries->resolve(codeFunctionName);
if (codep) {
uint8_t* (*codeFunction)(unsigned*);
memcpy(&codeFunction, &codep, BytesPerWord);
code = codeFunction(&size);
}
}
}
}
@ -2553,8 +2565,8 @@ Thread::init()
enter(this, ActiveState);
if (image) {
m->processor->boot(this, image);
if (image and image) {
m->processor->boot(this, image, code);
} else {
boot(this);
}

View File

@ -211,7 +211,7 @@ main(int ac, const char** av)
#endif
#ifdef BOOT_IMAGE
++ vmArgs.nOptions;
vmArgs.nOptions += 2;
#endif
#ifdef BOOT_BUILTINS
@ -225,7 +225,10 @@ main(int ac, const char** av)
#ifdef BOOT_IMAGE
vmArgs.options[optionIndex++].optionString
= const_cast<char*>("-Davian.bootimage=" BOOT_IMAGE);
= const_cast<char*>("-Davian.bootimage=bootimageBin");
vmArgs.options[optionIndex++].optionString
= const_cast<char*>("-Davian.codeimage=codeimageBin");
#endif
#ifdef BOOT_LIBRARY

View File

@ -135,7 +135,7 @@ class Processor {
makeCallTable(Thread* t, HeapWalker* w) = 0;
virtual void
boot(Thread* t, BootImage* image) = 0;
boot(Thread* t, BootImage* image, uint8_t* code) = 0;
virtual void
callWithCurrentContinuation(Thread* t, object receiver) = 0;

View File

@ -92,12 +92,15 @@ typedef int64_t target_intptr_t;
const unsigned TargetBytesPerWord = 8;
const unsigned TargetThreadTailAddress = 2272;
const unsigned TargetThreadStackLimit = 2336;
const unsigned TargetThreadStack = 2224;
const unsigned TargetThreadIp = 2216;
const unsigned TargetThreadStack = 2224;
const unsigned TargetThreadTailAddress = 2272;
const unsigned TargetThreadVirtualCallTarget = 2280;
const unsigned TargetThreadVirtualCallIndex = 2288;
const unsigned TargetThreadHeapImage = 2296;
const unsigned TargetThreadCodeImage = 2304;
const unsigned TargetThreadThunkTable = 2312;
const unsigned TargetThreadStackLimit = 2360;
const unsigned TargetClassFixedSize = 12;
const unsigned TargetClassArrayElementSize = 14;
@ -119,12 +122,15 @@ typedef int32_t target_intptr_t;
const unsigned TargetBytesPerWord = 4;
const unsigned TargetThreadTailAddress = 2172;
const unsigned TargetThreadStackLimit = 2204;
const unsigned TargetThreadStack = 2148;
const unsigned TargetThreadIp = 2144;
const unsigned TargetThreadStack = 2148;
const unsigned TargetThreadTailAddress = 2172;
const unsigned TargetThreadVirtualCallTarget = 2176;
const unsigned TargetThreadVirtualCallIndex = 2180;
const unsigned TargetThreadHeapImage = 2184;
const unsigned TargetThreadCodeImage = 2188;
const unsigned TargetThreadThunkTable = 2192;
const unsigned TargetThreadStackLimit = 2216;
const unsigned TargetClassFixedSize = 8;
const unsigned TargetClassArrayElementSize = 10;

View File

@ -345,8 +345,10 @@ void
appendOffsetTask(Context* c, Promise* promise, Promise* instructionOffset,
unsigned instructionSize)
{
c->tasks = new (c->zone->allocate(sizeof(OffsetTask))) OffsetTask
OffsetTask* task = new (c->zone->allocate(sizeof(OffsetTask))) OffsetTask
(c->tasks, promise, instructionOffset, instructionSize);
c->tasks = task;
}
void