diff --git a/makefile b/makefile index 946c31e62f..dca8d638a6 100644 --- a/makefile +++ b/makefile @@ -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) $(@) diff --git a/src/assembler.h b/src/assembler.h index 7b689123cd..126a3c21dc 100644 --- a/src/assembler.h +++ b/src/assembler.h @@ -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; }; diff --git a/src/boot.cpp b/src/boot.cpp index 9f4c96a612..9fca36f7f5 100644 --- a/src/boot.cpp +++ b/src/boot.cpp @@ -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 diff --git a/src/bootimage.cpp b/src/bootimage.cpp index e57cfd0f3f..85737f0922 100644 --- a/src/bootimage.cpp +++ b/src/bootimage.cpp @@ -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 (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 { diff --git a/src/bootimage.h b/src/bootimage.h index cfd73171d1..a868d02d74 100644 --- a/src/bootimage.h +++ b/src/bootimage.h @@ -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(heap + offset - 1); + } else { + return 0; + } } } // namespace vm diff --git a/src/compile.cpp b/src/compile.cpp index 3bfb70e480..9088f5c25c 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -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(callNodeAddress(t, node)), address); + updateCall + (t, LongCall, true, reinterpret_cast(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(heap + image->methodTree); - methodTreeSentinal = reinterpret_cast - (heap + image->methodTreeSentinal); + MyThread* t = static_cast(vmt); + methodTree = bootObject(heap, image->methodTree); + methodTreeSentinal = bootObject(heap, image->methodTreeSentinal); callTable = fixupCallTable - (static_cast(t), - reinterpret_cast(heap + image->callTable), - image->codeBase, + (t, bootObject(heap, image->callTable), image->codeBase, reinterpret_cast(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(voidPointer(compileMethod))); + { uint8_t* call = static_cast + (defaultContext.promise.listener->resolve + (reinterpret_cast(voidPointer(compileMethod)))) + + BytesPerWord; + if (image) { image->defaultThunk = p->defaultThunk - imageBase; - image->compileMethodCall = static_cast(call) - imageBase; + image->compileMethodCall = call - imageBase; } } p->nativeThunk = finish (t, allocator, nativeContext.context.assembler, "native"); - { void* call = nativeContext.promise.listener->resolve - (reinterpret_cast(voidPointer(invokeNative))); + { uint8_t* call = static_cast + (nativeContext.promise.listener->resolve + (reinterpret_cast(voidPointer(invokeNative)))) + + BytesPerWord; if (image) { image->nativeThunk = p->nativeThunk - imageBase; - image->invokeNativeCall = static_cast(call) - imageBase; + image->invokeNativeCall = call - imageBase; } } p->aioobThunk = finish (t, allocator, aioobContext.context.assembler, "aioob"); - { void* call = aioobContext.promise.listener->resolve - (reinterpret_cast(voidPointer(throwArrayIndexOutOfBounds))); + { uint8_t* call = static_cast + (aioobContext.promise.listener->resolve + (reinterpret_cast(voidPointer(throwArrayIndexOutOfBounds)))) + + BytesPerWord; if (image) { image->aioobThunk = p->aioobThunk - imageBase; - image->throwArrayIndexOutOfBoundsCall - = static_cast(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(voidPointer(s))); \ + { uint8_t* call = static_cast \ + (tableContext.promise.listener->resolve \ + (reinterpret_cast(voidPointer(s)))) + BytesPerWord; \ if (image) { \ - image->s##Call = static_cast(call) - imageBase; \ + image->s##Call = call - imageBase; \ } \ } diff --git a/src/heapwalk.cpp b/src/heapwalk.cpp index aa8e981e79..f6e2b746fe 100644 --- a/src/heapwalk.cpp +++ b/src/heapwalk.cpp @@ -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; diff --git a/src/heapwalk.h b/src/heapwalk.h index 473856bea3..25c681d6a3 100644 --- a/src/heapwalk.h +++ b/src/heapwalk.h @@ -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; }; diff --git a/src/machine.cpp b/src/machine.cpp index e64e892ebc..9c75036e97 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -1517,11 +1517,8 @@ boot(Thread* t, BootImage* image) if (w) { for (unsigned bit = 0; bit < BitsPerWord; ++bit) { if (w & (static_cast(1) << bit)) { - unsigned index = ::indexOf(word, bit); - uintptr_t* p = heap + index; - if (*p) { - *p = reinterpret_cast(heap + *p - 1); - } + uintptr_t* p = heap + indexOf(word, bit); + *p = reinterpret_cast(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(heap + image->loader); - t->m->stringMap = reinterpret_cast(heap + image->stringMap); - t->m->types = reinterpret_cast(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(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(heap + v - 1); - memcpy(code + index, &v, BytesPerWord); - } + v = reinterpret_cast(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 { diff --git a/src/main.cpp b/src/main.cpp index b784314579..5e412c0bae 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -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("-Davian.bootimage=" BOOT_IMAGE); +#endif + #ifdef BOOT_CLASSPATH options[optionIndex++].optionString = const_cast("-Xbootclasspath:" BOOT_CLASSPATH); diff --git a/src/x86.cpp b/src/x86.cpp index e0956deb3b..cb7d778612 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -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(returnAddress) - 5; - assert(&c, *instruction == 0xE8); - assert(&c, reinterpret_cast(instruction + 1) % 4 == 0); + assert(&c, (op == LongCall and *instruction == 0xE8) + or (op == LongJump and *instruction == 0xE9)); + assert(&c, (not assertAlignment) + or reinterpret_cast(instruction + 1) % 4 == 0); int32_t v = static_cast(newTarget) - static_cast(returnAddress);