diff --git a/src/arm.cpp b/src/arm.cpp index 4abb6cf17e..d0bb5f02c7 100644 --- a/src/arm.cpp +++ b/src/arm.cpp @@ -1618,7 +1618,7 @@ argumentFootprint(unsigned footprint) void nextFrame(ArchitectureContext* c, uint32_t* start, unsigned size UNUSED, - unsigned footprint, int32_t*, void* link, void*, + unsigned footprint, void* link, void*, unsigned targetParameterFootprint UNUSED, void** ip, void** stack) { assert(c, *ip >= start); @@ -1891,12 +1891,12 @@ class MyArchitecture: public Assembler::Architecture { } virtual void nextFrame(void* start, unsigned size, unsigned footprint, - int32_t* frameTable, void* link, void* stackLimit, + void* link, void* stackLimit, unsigned targetParameterFootprint, void** ip, void** stack) { - ::nextFrame(&c, static_cast(start), size, footprint, frameTable, - link, stackLimit, targetParameterFootprint, ip, stack); + ::nextFrame(&c, static_cast(start), size, footprint, link, + stackLimit, targetParameterFootprint, ip, stack); } virtual void* frameIp(void* stack) { @@ -1923,12 +1923,6 @@ class MyArchitecture: public Assembler::Architecture { return 0; } - virtual void nextFrame(void** stack, void**) { - assert(&c, *static_cast(*stack) != *stack); - - *stack = *static_cast(*stack); - } - virtual BinaryOperation hasBinaryIntrinsic(Thread*, object) { return NoBinaryOperation; } @@ -2120,6 +2114,18 @@ class MyAssembler: public Assembler { return arch_; } + virtual void checkStackOverflow(uintptr_t handler, + unsigned stackLimitOffsetFromThread) + { + Register stack(StackRegister); + Memory stackLimit(ThreadRegister, stackLimitOffsetFromThread); + Constant handlerConstant + (new (c.zone->allocate(sizeof(ResolvedPromise))) + ResolvedPromise(handler)); + branchRM(&c, JumpIfGreaterOrEqual, BytesPerWord, &stack, &stackLimit, + &handlerConstant); + } + virtual void saveFrame(unsigned stackOffset) { Register stack(StackRegister); Memory stackDst(ThreadRegister, stackOffset); @@ -2444,11 +2450,7 @@ class MyAssembler: public Assembler { return c.code.length(); } - virtual unsigned frameEventCount() { - return 0; - } - - virtual FrameEvent* firstFrameEvent() { + virtual unsigned footerSize() { return 0; } diff --git a/src/assembler.h b/src/assembler.h index 7edc0b9001..d122a53207 100644 --- a/src/assembler.h +++ b/src/assembler.h @@ -304,12 +304,6 @@ class Assembler { virtual unsigned resolve(unsigned start, Block* next) = 0; }; - class FrameEvent { - public: - virtual unsigned offset() = 0; - virtual FrameEvent* next() = 0; - }; - class Architecture { public: virtual unsigned floatRegisterSize() = 0; @@ -351,7 +345,7 @@ class Assembler { virtual unsigned alignFrameSize(unsigned sizeInWords) = 0; virtual void nextFrame(void* start, unsigned size, unsigned footprint, - int32_t* frameTable, void* link, void* stackLimit, + void* link, void* stackLimit, unsigned targetParameterFootprint, void** ip, void** stack) = 0; virtual void* frameIp(void* stack) = 0; @@ -401,6 +395,8 @@ class Assembler { virtual Architecture* arch() = 0; + virtual void checkStackOverflow(uintptr_t handler, + unsigned stackLimitOffsetFromThread) = 0; virtual void saveFrame(unsigned stackOffset) = 0; virtual void pushFrame(unsigned argumentCount, ...) = 0; virtual void allocateFrame(unsigned footprint) = 0; @@ -440,9 +436,7 @@ class Assembler { virtual unsigned length() = 0; - virtual unsigned frameEventCount() = 0; - - virtual FrameEvent* firstFrameEvent() = 0; + virtual unsigned footerSize() = 0; virtual void dispose() = 0; }; diff --git a/src/compile.cpp b/src/compile.cpp index 67e2644263..cb4bd365d2 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -396,35 +396,10 @@ alignedFrameSize(MyThread* t, object method) + t->arch->frameFootprint(MaxNativeCallFootprint)); } -unsigned -bitsNeeded(unsigned v) -{ - return log(v + 1); -} - -void -setTableValue(Thread* t, object table, unsigned base, unsigned max, - unsigned index, unsigned value) -{ - unsigned bits = bitsNeeded(max); - setBits - (&intArrayBody(t, table, base), bits, index * bits, value); -} - -unsigned -getTableValue(Thread* t, object table, unsigned base, unsigned max, - unsigned index) -{ - unsigned bits = bitsNeeded(max); - return getBits - (&intArrayBody(t, table, base), bits, index * bits); -} - void nextFrame(MyThread* t, void** ip, void** sp, object method, object target) { object code = methodCode(t, method); - object table = codeFrameTable(t, code); intptr_t start = codeCompiled(t, code); void* link; void* javaStackLimit; @@ -454,9 +429,8 @@ nextFrame(MyThread* t, void** ip, void** sp, object method, object target) t->arch->nextFrame (reinterpret_cast(start), compiledSize(start), - alignedFrameSize(t, method), table ? &intArrayBody(t, table, 0) : 0, - link, javaStackLimit, target ? methodParameterFootprint(t, target) : -1, - ip, sp); + alignedFrameSize(t, method), link, javaStackLimit, + target ? methodParameterFootprint(t, target) : -1, ip, sp); // fprintf(stderr, "next frame ip %p sp %p\n", *ip, *sp); } @@ -5226,37 +5200,6 @@ translateLineNumberTable(MyThread* t, Compiler* c, object code, intptr_t start) } } -object -makeFrameTable(MyThread* t, Context* c, unsigned codeSize) -{ - Assembler* a = c->assembler; - unsigned count = a->frameEventCount(); - if (count == 0) { - return 0; - } - - unsigned size = ceiling(count * bitsNeeded(codeSize), 32); - object table = makeIntArray(t, 1 + size); - - intArrayBody(t, table, 0) = count; - - unsigned index = 0; - for (Assembler::FrameEvent* e = a->firstFrameEvent(); - e; e = e->next()) - { - assert(t, index < count); - - unsigned offset = e->offset(); - assert(t, offset <= codeSize); - - setTableValue(t, table, 1, codeSize, index, offset); - - ++ index; - } - - return table; -} - void printSet(uintptr_t m, unsigned limit) { @@ -5943,14 +5886,10 @@ finish(MyThread* t, Allocator* allocator, Context* context) (t, c, methodCode(t, context->method), reinterpret_cast(start)); - PROTECT(t, newLineNumberTable); - - object frameTable = makeFrameTable(t, context, codeSize); - object code = methodCode(t, context->method); code = makeCode - (t, 0, newExceptionHandlerTable, newLineNumberTable, frameTable, + (t, 0, newExceptionHandlerTable, newLineNumberTable, reinterpret_cast(start), codeMaxStack(t, code), codeMaxLocals(t, code), 0); diff --git a/src/compiler.cpp b/src/compiler.cpp index 65b5437cad..18dc98e06f 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -5720,12 +5720,7 @@ compile(Context* c, uintptr_t stackOverflowHandler, unsigned stackLimitOffset) Block* block = firstBlock; if (stackOverflowHandler) { - Assembler::Register stack(c->arch->stack()); - Assembler::Memory stackLimit(c->arch->thread(), stackLimitOffset); - Assembler::Constant handler(resolved(c, stackOverflowHandler)); - a->apply(JumpIfGreaterOrEqual, BytesPerWord, RegisterOperand, &stack, - BytesPerWord, MemoryOperand, &stackLimit, - BytesPerWord, ConstantOperand, &handler); + a->checkStackOverflow(stackOverflowHandler, stackLimitOffset); } a->allocateFrame(c->alignedFrameSize); @@ -5854,7 +5849,7 @@ compile(Context* c, uintptr_t stackOverflowHandler, unsigned stackLimitOffset) block = next; } - return block->assemblerBlock->resolve(block->start, 0); + return block->assemblerBlock->resolve(block->start, 0) + a->footerSize(); } unsigned diff --git a/src/machine.cpp b/src/machine.cpp index 21338c441b..da705b5db6 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -1227,7 +1227,7 @@ parseCode(Thread* t, Stream& s, object pool) unsigned maxLocals = s.read2(); unsigned length = s.read4(); - object code = makeCode(t, pool, 0, 0, 0, 0, maxStack, maxLocals, length); + object code = makeCode(t, pool, 0, 0, 0, maxStack, maxLocals, length); s.read(&codeBody(t, code, 0), length); PROTECT(t, code); @@ -2065,7 +2065,7 @@ boot(Thread* t) m->processor->boot(t, 0); - { object bootCode = makeCode(t, 0, 0, 0, 0, 0, 0, 0, 1); + { object bootCode = makeCode(t, 0, 0, 0, 0, 0, 0, 1); codeBody(t, bootCode, 0) = impdep1; object bootMethod = makeMethod (t, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, bootCode); diff --git a/src/powerpc.cpp b/src/powerpc.cpp index be5cfac378..55c2658dc0 100644 --- a/src/powerpc.cpp +++ b/src/powerpc.cpp @@ -191,13 +191,15 @@ class MyBlock: public Assembler::Block { class Task; class ConstantPoolEntry; +class JumpPromise; class Context { public: Context(System* s, Allocator* a, Zone* zone): s(s), zone(zone), client(0), code(s, a, 1024), tasks(0), result(0), firstBlock(new (zone->allocate(sizeof(MyBlock))) MyBlock(0)), - lastBlock(firstBlock), constantPool(0), constantPoolCount(0) + lastBlock(firstBlock), constantPool(0), jumps(0), constantPoolCount(0), + jumpCount(0) { } System* s; @@ -209,7 +211,9 @@ class Context { MyBlock* firstBlock; MyBlock* lastBlock; ConstantPoolEntry* constantPool; + JumpPromise* jumps; unsigned constantPoolCount; + unsigned jumpCount; }; class Task { @@ -312,6 +316,38 @@ offset(Context* c) Offset(c, c->lastBlock, c->code.length()); } +class JumpPromise: public Promise { + public: + JumpPromise(Context* c, uintptr_t target): + c(c), target(target), next(c->jumps), index(c->jumpCount++) + { + c->jumps = this; + } + + virtual bool resolved() { + return c->result != 0; + } + + virtual int64_t value() { + assert(c, resolved()); + + return reinterpret_cast + (c->result + c->code.length() + (index * BytesPerWord)); + } + + Context* c; + uintptr_t target; + JumpPromise* next; + unsigned index; +}; + +Promise* +jump(Context* c, uintptr_t target) +{ + return new (c->zone->allocate(sizeof(JumpPromise))) + JumpPromise(c, target); +} + bool bounded(int right, int left, int32_t v) { @@ -659,7 +695,6 @@ class ConstantPoolEntry: public Promise { Promise* constant; ConstantPoolEntry* next; void* address; - unsigned constantPoolCount; }; ConstantPoolEntry* @@ -1699,7 +1734,7 @@ argumentFootprint(unsigned footprint) void nextFrame(ArchitectureContext* c UNUSED, int32_t* start, unsigned size UNUSED, - unsigned footprint, int32_t*, void* link, void*, + unsigned footprint, void* link, void*, unsigned targetParameterFootprint, void** ip, void** stack) { assert(c, *ip >= start); @@ -1970,12 +2005,12 @@ class MyArchitecture: public Assembler::Architecture { } virtual void nextFrame(void* start, unsigned size, unsigned footprint, - int32_t* frameTable, void* link, void* stackLimit, + void* link, void* stackLimit, unsigned targetParameterFootprint, void** ip, void** stack) { - ::nextFrame(&c, static_cast(start), size, footprint, frameTable, - link, stackLimit, targetParameterFootprint, ip, stack); + ::nextFrame(&c, static_cast(start), size, footprint, link, + stackLimit, targetParameterFootprint, ip, stack); } virtual void* frameIp(void* stack) { @@ -2002,12 +2037,6 @@ class MyArchitecture: public Assembler::Architecture { return 0; } - virtual void nextFrame(void** stack, void**) { - assert(&c, *static_cast(*stack) != *stack); - - *stack = *static_cast(*stack); - } - virtual BinaryOperation hasBinaryIntrinsic(Thread*, object) { return NoBinaryOperation; } @@ -2203,6 +2232,16 @@ class MyAssembler: public Assembler { return arch_; } + virtual void checkStackOverflow(uintptr_t handler, + unsigned stackLimitOffsetFromThread) + { + Register stack(StackRegister); + Memory stackLimit(ThreadRegister, stackLimitOffsetFromThread); + Constant handlerConstant(jump(&c, handler)); + branchRM(&c, JumpIfGreaterOrEqual, BytesPerWord, &stack, &stackLimit, + &handlerConstant); + } + virtual void saveFrame(unsigned stackOffset) { Register returnAddress(0); emit(&c, mflr(returnAddress.low)); @@ -2420,12 +2459,20 @@ class MyAssembler: public Assembler { virtual void writeTo(uint8_t* dst) { c.result = dst; - + for (MyBlock* b = c.firstBlock; b; b = b->next) { memcpy(dst + b->start, c.code.data + b->offset, b->size); } + + for (JumpPromise* j = c.jumps; j; j = j->next) { + uint8_t* instruction + = dst + c.code.length() + (c.jumpCount - j->index - 1); + int32_t op = ::b(0); + memcpy(instruction, &op, BytesPerWord); + updateOffset(c.s, instruction, false, j->target); + } - unsigned index = c.code.length(); + unsigned index = c.code.length() + (c.jumpCount * BytesPerWord); assert(&c, index % BytesPerWord == 0); for (ConstantPoolEntry* e = c.constantPool; e; e = e->next) { e->address = dst + index; @@ -2466,12 +2513,8 @@ class MyAssembler: public Assembler { return c.code.length(); } - virtual unsigned frameEventCount() { - return 0; - } - - virtual FrameEvent* firstFrameEvent() { - return 0; + virtual unsigned footerSize() { + return (c.jumpCount + c.constantPoolCount) * BytesPerWord; } virtual void dispose() { diff --git a/src/types.def b/src/types.def index 24d4b1854c..8b8d980ffc 100644 --- a/src/types.def +++ b/src/types.def @@ -86,7 +86,6 @@ (object pool) (object exceptionHandlerTable) (object lineNumberTable) - (object frameTable) (intptr_t compiled) (uint16_t maxStack) (uint16_t maxLocals) diff --git a/src/x86.cpp b/src/x86.cpp index c2432e2ad8..0f7a672459 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -86,7 +86,7 @@ isInt32(intptr_t v) class Task; class AlignmentPadding; -class MyFrameEvent; +class FrameEvent; unsigned padding(AlignmentPadding* p, unsigned index, unsigned offset, @@ -115,8 +115,8 @@ class MyBlock: public Assembler::Block { MyBlock* next; AlignmentPadding* firstPadding; AlignmentPadding* lastPadding; - MyFrameEvent* firstFrameEvent; - MyFrameEvent* lastFrameEvent; + FrameEvent* firstFrameEvent; + FrameEvent* lastFrameEvent; unsigned offset; unsigned start; unsigned size; @@ -171,8 +171,8 @@ class Context { uint8_t* result; MyBlock* firstBlock; MyBlock* lastBlock; - MyFrameEvent* firstFrameEvent; - MyFrameEvent* lastFrameEvent; + FrameEvent* firstFrameEvent; + FrameEvent* lastFrameEvent; ArchitectureContext* ac; unsigned frameEventCount; }; @@ -461,33 +461,25 @@ padding(AlignmentPadding* p, unsigned start, unsigned offset, return padding; } -class MyFrameEvent: public Assembler::FrameEvent { +class FrameEvent { public: - MyFrameEvent(Context* c, Promise* offset): - c(c), next_(0), offset_(offset) + FrameEvent(Context* c, Promise* offset): + c(c), next(0), offset(offset) { } - virtual unsigned offset() { - return offset_->value(); - } - - virtual Assembler::FrameEvent* next() { - return next_; - } - Context* c; - MyFrameEvent* next_; - Promise* offset_; + FrameEvent* next; + Promise* offset; }; void appendFrameEvent(Context* c, MyBlock* b, Promise* offset) { - MyFrameEvent* e = new (c->zone->allocate(sizeof(MyFrameEvent))) - MyFrameEvent(c, offset); + FrameEvent* e = new (c->zone->allocate(sizeof(FrameEvent))) + FrameEvent(c, offset); if (b->firstFrameEvent) { - b->lastFrameEvent->next_ = e; + b->lastFrameEvent->next = e; } else { b->firstFrameEvent = e; } @@ -2577,7 +2569,7 @@ read4(uint8_t* p) void nextFrame(ArchitectureContext* c UNUSED, uint8_t* start, unsigned size UNUSED, - unsigned footprint, int32_t*, void*, void* stackLimit, + unsigned footprint, void*, void* stackLimit, unsigned targetParameterFootprint, void** ip, void** stack) { assert(c, *ip >= start); @@ -2643,7 +2635,7 @@ nextFrame(ArchitectureContext* c UNUSED, uint8_t* start, unsigned size UNUSED, / BytesPerWord; } - // todo: use frameTable to check for and handle tail calls + // todo: check for and handle tail calls } *ip = static_cast(*stack)[offset]; @@ -2977,13 +2969,12 @@ class MyArchitecture: public Assembler::Architecture { } virtual void nextFrame(void* start, unsigned size, unsigned footprint, - int32_t* frameTable, void* link, void* stackLimit, + void* link, void* stackLimit, unsigned targetParameterFootprint, void** ip, void** stack) { local::nextFrame(&c, static_cast(start), size, footprint, - frameTable, link, stackLimit, targetParameterFootprint, - ip, stack); + link, stackLimit, targetParameterFootprint, ip, stack); } virtual void* frameIp(void* stack) { @@ -3421,6 +3412,16 @@ class MyAssembler: public Assembler { return arch_; } + virtual void checkStackOverflow(uintptr_t handler, + unsigned stackLimitOffsetFromThread) + { + Register stack(rsp); + Memory stackLimit(rbx, stackLimitOffsetFromThread); + Constant handlerConstant(resolved(&c, handler)); + branchRM(&c, JumpIfGreaterOrEqual, BytesPerWord, &stack, &stackLimit, + &handlerConstant); + } + virtual void saveFrame(unsigned stackOffset) { Register stack(rsp); Memory stackDst(rbx, stackOffset); @@ -3661,7 +3662,7 @@ class MyAssembler: public Assembler { for (MyBlock* b = c.firstBlock; b; b = b->next) { if (b->firstFrameEvent) { if (c.firstFrameEvent) { - c.lastFrameEvent->next_ = b->firstFrameEvent; + c.lastFrameEvent->next = b->firstFrameEvent; } else { c.firstFrameEvent = b->firstFrameEvent; } @@ -3721,12 +3722,8 @@ class MyAssembler: public Assembler { return c.code.length(); } - virtual unsigned frameEventCount() { - return c.frameEventCount; - } - - virtual FrameEvent* firstFrameEvent() { - return c.firstFrameEvent; + virtual unsigned footerSize() { + return 0; } virtual void dispose() {