update makefile to optionally build and use a boot image; various bugfixes

This commit is contained in:
Joel Dice 2008-11-29 16:08:14 -07:00
parent 0ef2ee1d02
commit 0ec5ad3701
11 changed files with 178 additions and 85 deletions

View File

@ -59,7 +59,6 @@ warnings = -Wall -Wextra -Werror -Wunused-parameter -Winit-self \
common-cflags = $(warnings) -fno-rtti -fno-exceptions -fno-omit-frame-pointer \
"-I$(JAVA_HOME)/include" -idirafter $(src) -I$(native-build) \
-D__STDC_LIMIT_MACROS -D_JNI_IMPLEMENTATION_ -DAVIAN_VERSION=\"$(version)\" \
-DBOOT_CLASSPATH=\"[classpathJar]\"
build-cflags = $(common-cflags) -fPIC -fvisibility=hidden \
"-I$(JAVA_HOME)/include/linux" -I$(src) -pthread
@ -187,7 +186,9 @@ vm-depends = \
$(src)/util.h \
$(src)/zone.h \
$(src)/assembler.h \
$(src)/compiler.h
$(src)/compiler.h \
$(src)/heapwalk.h \
$(src)/bootimage.h
vm-sources = \
$(src)/$(system).cpp \
@ -227,10 +228,21 @@ ifeq ($(heapdump),true)
cflags += -DAVIAN_HEAPDUMP
endif
bootimage-sources = $(src)/bootimage.cpp
bootimage-objects = \
$(call cpp-objects,$(bootimage-sources),$(src),$(native-build))
bootimage = $(native-build)/bootimage
bootimage-generator-sources = $(src)/bootimage.cpp
bootimage-generator-objects = \
$(call cpp-objects,$(bootimage-generator-sources),$(src),$(native-build))
bootimage-generator = $(native-build)/bootimage-generator
bootimage-bin = $(native-build)/bootimage.bin
bootimage-object = $(native-build)/bootimage-bin.o
ifeq ($(bootimage),true)
vm-classpath-object = $(bootimage-object)
cflags += -DBOOT_IMAGE=\"bootimageBin\"
else
vm-classpath-object = $(classpath-object)
cflags += -DBOOT_CLASSPATH=\"[classpathJar]\"
endif
driver-source = $(src)/main.cpp
driver-object = $(native-build)/main.o
@ -269,7 +281,7 @@ args = $(flags) $(input)
.PHONY: build
build: $(static-library) $(executable) $(dynamic-library) \
$(executable-dynamic) $(classpath-dep) $(test-dep) $(bootimage)
$(executable-dynamic) $(classpath-dep) $(test-dep)
$(test-classes): $(classpath-dep)
@ -356,7 +368,7 @@ $(vm-cpp-objects): $(native-build)/%.o: $(src)/%.cpp $(vm-depends)
$(vm-asm-objects): $(native-build)/%-asm.o: $(src)/%.S
$(compile-asm-object)
$(bootimage-objects): $(native-build)/%.o: $(src)/%.cpp $(vm-depends)
$(bootimage-generator-objects): $(native-build)/%.o: $(src)/%.cpp $(vm-depends)
$(compile-object)
$(heapwalk-objects): $(native-build)/%.o: $(src)/%.cpp $(vm-depends)
@ -409,9 +421,24 @@ $(static-library): $(vm-objects) $(jni-objects)
$(ar) cru $(@) $(^)
$(ranlib) $(@)
$(bootimage-bin): $(bootimage-generator)
$(<) $(classpath-build) > $(@)
$(bootimage-object): $(bootimage-bin)
@echo "creating $(@)"
ifeq ($(platform),darwin)
$(binaryToMacho) $(<) \
__binary_bootimage_bin_start __binary_bootimage_bin_end > $(@)
else
(wd=$$(pwd); \
cd $(native-build); \
$(objcopy) -I binary bootimage.bin \
-O $(object-format) -B $(object-arch) "$${wd}/$(@)")
endif
$(executable): \
$(vm-objects) $(classpath-object) $(jni-objects) $(driver-object) \
$(vm-heapwalk-objects) $(boot-object)
$(vm-objects) $(jni-objects) $(driver-object) $(vm-heapwalk-objects) \
$(boot-object) $(vm-classpath-object)
@echo "linking $(@)"
ifeq ($(platform),windows)
$(dlltool) -z $(@).def $(^)
@ -422,9 +449,9 @@ else
endif
$(strip) $(strip-all) $(@)
$(bootimage): \
$(bootimage-generator): \
$(vm-objects) $(classpath-object) $(jni-objects) $(heapwalk-objects) \
$(bootimage-objects)
$(bootimage-generator-objects)
@echo "linking $(@)"
ifeq ($(platform),windows)
$(dlltool) -z $(@).def $(^)
@ -436,8 +463,8 @@ endif
$(strip) $(strip-all) $(@)
$(dynamic-library): \
$(vm-objects) $(classpath-object) $(dynamic-object) $(jni-objects) \
$(vm-heapwalk-objects) $(boot-object)
$(vm-objects) $(dynamic-object) $(jni-objects) $(vm-heapwalk-objects) \
$(boot-object) $(vm-classpath-object)
@echo "linking $(@)"
$(cc) $(^) $(shared) $(lflags) -o $(@)
$(strip) $(strip-all) $(@)

View File

@ -211,7 +211,8 @@ class Assembler {
virtual unsigned length() = 0;
virtual void updateCall(void* returnAddress, void* newTarget) = 0;
virtual void updateCall(UnaryOperation op, bool assertAlignment,
void* returnAddress, void* newTarget) = 0;
virtual void dispose() = 0;
};

View File

@ -15,6 +15,34 @@
// ourselves:
extern "C" void __cxa_pure_virtual(void) { abort(); }
#ifdef BOOT_IMAGE
#ifdef __MINGW32__
# define EXPORT __declspec(dllexport)
# define SYMBOL(x) binary_bootimage_bin_##x
#else
# define EXPORT __attribute__ ((visibility("default")))
# define SYMBOL(x) _binary_bootimage_bin_##x
#endif
extern "C" {
extern const uint8_t SYMBOL(start)[];
extern const uint8_t SYMBOL(end)[];
EXPORT const uint8_t*
bootimageBin(unsigned* size)
{
*size = SYMBOL(end) - SYMBOL(start);
return SYMBOL(start);
}
}
#endif//BOOT_IMAGE
#ifdef BOOT_CLASSPATH
#ifdef __MINGW32__
# define EXPORT __declspec(dllexport)
# define SYMBOL(x) binary_classpath_jar_##x
@ -36,3 +64,5 @@ extern "C" {
}
}
#endif//BOOT_CLASSPATH

View File

@ -106,22 +106,18 @@ makeHeapImage(Thread* t, BootImage* image, uintptr_t* heap, uintptr_t* map,
class Visitor: public HeapVisitor {
public:
Visitor(Thread* t, uintptr_t* heap, uintptr_t* map, unsigned capacity):
t(t), currentObject(0), currentOffset(0), heap(heap), map(map),
position(0), capacity(capacity)
t(t), current(0), heap(heap), map(map), position(0), capacity(capacity)
{ }
void visit(unsigned number) {
if (currentObject) {
unsigned index = currentObject - 1 + currentOffset;
markBit(map, index);
heap[index] = number;
if (current) {
if (number) markBit(map, current - 1);
heap[current - 1] = number;
}
currentObject = number;
}
virtual void root() {
currentObject = 0;
current = 0;
}
virtual unsigned visitNew(object p) {
@ -146,17 +142,16 @@ makeHeapImage(Thread* t, BootImage* image, uintptr_t* heap, uintptr_t* map,
visit(number);
}
virtual void push(unsigned offset) {
currentOffset = offset;
virtual void push(object, unsigned number, unsigned offset) {
current = number + offset;
}
virtual void pop() {
currentObject = 0;
current = 0;
}
Thread* t;
unsigned currentObject;
unsigned currentOffset;
unsigned current;
uintptr_t* heap;
uintptr_t* map;
unsigned position;
@ -176,8 +171,8 @@ updateConstants(Thread* t, object constants, uint8_t* code, uintptr_t* codeMap,
HeapMap* heapTable)
{
for (; constants; constants = tripleThird(t, constants)) {
intptr_t target = heapTable->find(tripleFirst(t, constants));
assert(t, target >= 0);
unsigned target = heapTable->find(tripleFirst(t, constants));
assert(t, target > 0);
void* dst = static_cast<ListenPromise*>
(pointerValue(t, tripleSecond(t, constants)))->listener->resolve(target);
@ -226,7 +221,7 @@ writeBootImage(Thread* t, FILE* out)
image.magic = BootImage::Magic;
if (true) {
if (false) {
fprintf(stderr, "heap size %d code size %d\n",
image.heapSize, image.codeSize);
} else {

View File

@ -59,7 +59,17 @@ codeMapSize(unsigned codeSize)
inline unsigned
heapMapSize(unsigned heapSize)
{
return ceiling(heapSize, BitsPerWord * 8) * BytesPerWord;
return ceiling(heapSize, BitsPerWord * BytesPerWord) * BytesPerWord;
}
inline object
bootObject(uintptr_t* heap, unsigned offset)
{
if (offset) {
return reinterpret_cast<object>(heap + offset - 1);
} else {
return 0;
}
}
} // namespace vm

View File

@ -4050,6 +4050,14 @@ compile(MyThread* t, Allocator* allocator, Context* context)
return finish(t, allocator, context);
}
void
updateCall(MyThread* t, UnaryOperation op, bool assertAlignment,
void* returnAddress, void* target)
{
Context context(t);
context.assembler->updateCall(op, assertAlignment, returnAddress, target);
}
void
compile(MyThread* t, Allocator* allocator, BootContext* bootContext,
object method);
@ -4081,9 +4089,9 @@ compileMethod2(MyThread* t)
(t, resolveThisPointer(t, t->stack, target)), methodOffset(t, target))
= address;
} else {
Context context(t);
context.assembler->updateCall
(reinterpret_cast<void*>(callNodeAddress(t, node)), address);
updateCall
(t, LongCall, true, reinterpret_cast<void*>(callNodeAddress(t, node)),
address);
}
return address;
}
@ -5117,37 +5125,38 @@ class MyProcessor: public Processor {
image->methodTreeSentinal = w->visitRoot(methodTreeSentinal);
}
virtual void boot(Thread* t, BootImage* image, uintptr_t* heap,
virtual void boot(Thread* vmt, BootImage* image, uintptr_t* heap,
uint8_t* code)
{
methodTree = reinterpret_cast<object>(heap + image->methodTree);
methodTreeSentinal = reinterpret_cast<object>
(heap + image->methodTreeSentinal);
MyThread* t = static_cast<MyThread*>(vmt);
methodTree = bootObject(heap, image->methodTree);
methodTreeSentinal = bootObject(heap, image->methodTreeSentinal);
callTable = fixupCallTable
(static_cast<MyThread*>(t),
reinterpret_cast<object>(heap + image->callTable),
image->codeBase,
(t, bootObject(heap, image->callTable), image->codeBase,
reinterpret_cast<uintptr_t>(code));
defaultThunk = code + image->defaultThunk;
{ void* p = voidPointer(::compileMethod);
memcpy(code + image->compileMethodCall, &p, BytesPerWord); }
updateCall(t, LongCall, false, code + image->compileMethodCall,
voidPointer(::compileMethod));
nativeThunk = code + image->nativeThunk;
{ void* p = voidPointer(invokeNative);
memcpy(code + image->invokeNativeCall, &p, BytesPerWord); }
updateCall(t, LongCall, false, code + image->invokeNativeCall,
voidPointer(invokeNative));
aioobThunk = code + image->aioobThunk;
{ void* p = voidPointer(throwArrayIndexOutOfBounds);
memcpy(code + image->throwArrayIndexOutOfBoundsCall, &p, BytesPerWord); }
updateCall(t, LongCall, false,
code + image->throwArrayIndexOutOfBoundsCall,
voidPointer(throwArrayIndexOutOfBounds));
thunkTable = code + image->thunkTable;
thunkSize = image->thunkSize;
#define THUNK(s) \
{ void* p = voidPointer(s); \
memcpy(code + image->s##Call, &p, BytesPerWord); }
updateCall(t, LongJump, false, code + image->s##Call, voidPointer(s));
#include "thunks.cpp"
@ -5261,36 +5270,42 @@ compileThunks(MyThread* t, Allocator* allocator, MyProcessor* p,
p->defaultThunk = finish
(t, allocator, defaultContext.context.assembler, "default");
{ void* call = defaultContext.promise.listener->resolve
(reinterpret_cast<intptr_t>(voidPointer(compileMethod)));
{ uint8_t* call = static_cast<uint8_t*>
(defaultContext.promise.listener->resolve
(reinterpret_cast<intptr_t>(voidPointer(compileMethod))))
+ BytesPerWord;
if (image) {
image->defaultThunk = p->defaultThunk - imageBase;
image->compileMethodCall = static_cast<uint8_t*>(call) - imageBase;
image->compileMethodCall = call - imageBase;
}
}
p->nativeThunk = finish
(t, allocator, nativeContext.context.assembler, "native");
{ void* call = nativeContext.promise.listener->resolve
(reinterpret_cast<intptr_t>(voidPointer(invokeNative)));
{ uint8_t* call = static_cast<uint8_t*>
(nativeContext.promise.listener->resolve
(reinterpret_cast<intptr_t>(voidPointer(invokeNative))))
+ BytesPerWord;
if (image) {
image->nativeThunk = p->nativeThunk - imageBase;
image->invokeNativeCall = static_cast<uint8_t*>(call) - imageBase;
image->invokeNativeCall = call - imageBase;
}
}
p->aioobThunk = finish
(t, allocator, aioobContext.context.assembler, "aioob");
{ void* call = aioobContext.promise.listener->resolve
(reinterpret_cast<intptr_t>(voidPointer(throwArrayIndexOutOfBounds)));
{ uint8_t* call = static_cast<uint8_t*>
(aioobContext.promise.listener->resolve
(reinterpret_cast<intptr_t>(voidPointer(throwArrayIndexOutOfBounds))))
+ BytesPerWord;
if (image) {
image->aioobThunk = p->aioobThunk - imageBase;
image->throwArrayIndexOutOfBoundsCall
= static_cast<uint8_t*>(call) - imageBase;
image->throwArrayIndexOutOfBoundsCall = call - imageBase;
}
}
@ -5309,10 +5324,11 @@ compileThunks(MyThread* t, Allocator* allocator, MyProcessor* p,
#define THUNK(s) \
tableContext.context.assembler->writeTo(start); \
start += p->thunkSize; \
{ void* call = tableContext.promise.listener->resolve \
(reinterpret_cast<intptr_t>(voidPointer(s))); \
{ uint8_t* call = static_cast<uint8_t*> \
(tableContext.promise.listener->resolve \
(reinterpret_cast<intptr_t>(voidPointer(s)))) + BytesPerWord; \
if (image) { \
image->s##Call = static_cast<uint8_t*>(call) - imageBase; \
image->s##Call = call - imageBase; \
} \
}

View File

@ -266,7 +266,7 @@ walk(Context* c, HeapVisitor* v, object p)
goto pop;
children: {
v->push(nextChildOffset);
v->push(p, find(c, p)->number, nextChildOffset);
push(c, p, nextChildOffset);
p = get(p, nextChildOffset);
goto visit;

View File

@ -28,7 +28,8 @@ class HeapVisitor {
virtual void root() = 0;
virtual unsigned visitNew(object value) = 0;
virtual void visitOld(object value, unsigned number) = 0;
virtual void push(unsigned offset) = 0;
virtual void push(object parent, unsigned parentNumber,
unsigned childOffset) = 0;
virtual void pop() = 0;
};

View File

@ -1517,11 +1517,8 @@ boot(Thread* t, BootImage* image)
if (w) {
for (unsigned bit = 0; bit < BitsPerWord; ++bit) {
if (w & (static_cast<uintptr_t>(1) << bit)) {
unsigned index = ::indexOf(word, bit);
uintptr_t* p = heap + index;
if (*p) {
*p = reinterpret_cast<uintptr_t>(heap + *p - 1);
}
uintptr_t* p = heap + indexOf(word, bit);
*p = reinterpret_cast<uintptr_t>(heap + (*p - 1));
}
}
heapMap[word] = 0;
@ -1530,9 +1527,9 @@ boot(Thread* t, BootImage* image)
t->m->heap->setImmortalHeap(heap, image->heapSize, heapMap);
t->m->loader = reinterpret_cast<object>(heap + image->loader);
t->m->stringMap = reinterpret_cast<object>(heap + image->stringMap);
t->m->types = reinterpret_cast<object>(heap + image->types);
t->m->loader = bootObject(heap, image->loader);
t->m->stringMap = bootObject(heap, image->stringMap);
t->m->types = bootObject(heap, image->types);
uintptr_t* codeMap = heap + ceiling(image->heapSize, BytesPerWord);
unsigned codeMapSizeInWords = ceiling
@ -1544,12 +1541,10 @@ boot(Thread* t, BootImage* image)
if (w) {
for (unsigned bit = 0; bit < BitsPerWord; ++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);
if (v) {
v = reinterpret_cast<uintptr_t>(heap + v - 1);
memcpy(code + index, &v, BytesPerWord);
}
v = reinterpret_cast<uintptr_t>(heap + v - 1);
memcpy(code + index, &v, BytesPerWord);
}
}
}
@ -1580,6 +1575,8 @@ boot(Thread* t)
{
Machine* m = t->m;
m->unsafe = true;
m->loader = allocate(t, sizeof(void*) * 3, true);
memset(m->loader, 0, sizeof(void*) * 2);
@ -1882,6 +1879,8 @@ Thread::init()
}
}
m->unsafe = false;
if (image) {
boot(this, image);
} else {

View File

@ -79,11 +79,20 @@ main(int ac, const char** av)
++ vmArgs.nOptions;
#endif
#ifdef BOOT_IMAGE
++ vmArgs.nOptions;
#endif
JavaVMOption options[vmArgs.nOptions];
vmArgs.options = options;
unsigned optionIndex = 0;
#ifdef BOOT_IMAGE
options[optionIndex++].optionString
= const_cast<char*>("-Davian.bootimage=" BOOT_IMAGE);
#endif
#ifdef BOOT_CLASSPATH
options[optionIndex++].optionString
= const_cast<char*>("-Xbootclasspath:" BOOT_CLASSPATH);

View File

@ -135,7 +135,7 @@ class Task {
Task* next;
};
void
void*
resolveOffset(System* s, uint8_t* instruction, unsigned instructionSize,
int64_t value)
{
@ -146,6 +146,7 @@ resolveOffset(System* s, uint8_t* instruction, unsigned instructionSize,
int32_t v4 = v;
memcpy(instruction + instructionSize - 4, &v4, 4);
return instruction + instructionSize - 4;
}
class OffsetListener: public Promise::Listener {
@ -158,8 +159,7 @@ class OffsetListener: public Promise::Listener {
{ }
virtual void* resolve(int64_t value) {
resolveOffset(s, instruction, instructionSize, value);
return 0;
return resolveOffset(s, instruction, instructionSize, value);
}
System* s;
@ -2270,10 +2270,15 @@ class MyAssembler: public Assembler {
return c.code.length();
}
virtual void updateCall(void* returnAddress, void* newTarget) {
virtual void updateCall(UnaryOperation op UNUSED,
bool assertAlignment UNUSED, void* returnAddress,
void* newTarget)
{
uint8_t* instruction = static_cast<uint8_t*>(returnAddress) - 5;
assert(&c, *instruction == 0xE8);
assert(&c, reinterpret_cast<uintptr_t>(instruction + 1) % 4 == 0);
assert(&c, (op == LongCall and *instruction == 0xE8)
or (op == LongJump and *instruction == 0xE9));
assert(&c, (not assertAlignment)
or reinterpret_cast<uintptr_t>(instruction + 1) % 4 == 0);
int32_t v = static_cast<uint8_t*>(newTarget)
- static_cast<uint8_t*>(returnAddress);