From 7cfbdc8fdba9561bb0145fa8f685733811f46f97 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Fri, 14 Mar 2014 09:50:10 -0600 Subject: [PATCH 1/3] call crash if the signal handler is unable to handle the signal Otherwise, the OS will just keep asking us to handle the signal in an infinite loop. --- src/system/posix/signal.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/system/posix/signal.cpp b/src/system/posix/signal.cpp index bd4581697d..07d013372d 100644 --- a/src/system/posix/signal.cpp +++ b/src/system/posix/signal.cpp @@ -140,6 +140,8 @@ void handleSignal(int signal, siginfo_t*, void* context) pthread_sigmask(SIG_UNBLOCK, &set, 0); vmJump(ip, frame, stack, thread, 0, 0); + } else { + crash(); } } break; From 73e60adeab8e61d7027dedd460723ff44b8d42bd Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Fri, 14 Mar 2014 09:54:05 -0600 Subject: [PATCH 2/3] always add a trap instruction after a throw Tail call and dead code optimizations can cause code after a throw to be eliminated, which confuses findUnwindTarget because it doesn't know what code is throwing the exception. So we need at least one instruction to follow the call to the throw_ thunk. Previously, we only added such an instruction when we knew the throw was the last instruction in the bytecode, but it turns out there are other cases where it is needed, including certain try/finally situations. --- src/compile.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/compile.cpp b/src/compile.cpp index 39f8f4c357..5fc3fbea9c 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -4333,9 +4333,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp, Compiler::VoidType, 2, c->register_(t->arch->thread()), target); - if (ip == codeLength(t, code)) { - c->nullaryOp(lir::Trap); - } + c->nullaryOp(lir::Trap); } goto next; case bipush: From 918b7828f1fba1af977325cf2a558d1b5f1ba3be Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Fri, 14 Mar 2014 09:59:04 -0600 Subject: [PATCH 3/3] fix StackOverflowError stack walking in tails=true builds The various Architecture::nextFrame implementations were not walking the stack correctly when a StackOverflowError was thrown. The throwStackOverflow thunk is called before the frame of the most recently called method has been fully created, and because tails=true builds use a different calling convention, we need to treat this situation carefully when building a stack trace or unwinding. Otherwise, we will skip past all the java frames to the next native frame, which is what was happening. --- include/avian/codegen/architecture.h | 4 ++-- src/codegen/target/arm/assembler.cpp | 8 ++++---- src/codegen/target/powerpc/assembler.cpp | 6 +++--- src/codegen/target/x86/assembler.cpp | 16 ++++++++++++---- test/StackOverflow.java | 12 ++++++++++++ 5 files changed, 33 insertions(+), 13 deletions(-) diff --git a/include/avian/codegen/architecture.h b/include/avian/codegen/architecture.h index dca414fcfd..95cac96d4c 100644 --- a/include/avian/codegen/architecture.h +++ b/include/avian/codegen/architecture.h @@ -88,7 +88,7 @@ virtual unsigned alignFrameSize(unsigned sizeInWords) = 0; virtual void nextFrame(void* start, unsigned size, unsigned footprint, void* link, bool mostRecent, - unsigned targetParameterFootprint, void** ip, + int targetParameterFootprint, void** ip, void** stack) = 0; virtual void* frameIp(void* stack) = 0; virtual unsigned frameHeaderSize() = 0; @@ -138,4 +138,4 @@ virtual void release() = 0; } // namespace codegen } // namespace avian -#endif // AVIAN_CODEGEN_ARCHITECTURE_H \ No newline at end of file +#endif // AVIAN_CODEGEN_ARCHITECTURE_H diff --git a/src/codegen/target/arm/assembler.cpp b/src/codegen/target/arm/assembler.cpp index 3d61fe25ed..efe5aed594 100644 --- a/src/codegen/target/arm/assembler.cpp +++ b/src/codegen/target/arm/assembler.cpp @@ -83,7 +83,7 @@ argumentFootprint(unsigned footprint) void nextFrame(ArchitectureContext* con, uint32_t* start, unsigned size UNUSED, unsigned footprint, void* link, bool, - unsigned targetParameterFootprint UNUSED, void** ip, void** stack) + int targetParameterFootprint UNUSED, void** ip, void** stack) { assert(con, *ip >= start); assert(con, *ip <= start + (size / TargetBytesPerWord)); @@ -113,13 +113,13 @@ nextFrame(ArchitectureContext* con, uint32_t* start, unsigned size UNUSED, return; } - if (TailCalls) { + if (TailCalls and targetParameterFootprint >= 0) { if (argumentFootprint(targetParameterFootprint) > StackAlignmentInWords) { offset += argumentFootprint(targetParameterFootprint) - StackAlignmentInWords; } - // check for post-non-tail-call stack adjustment of the form "add + // check for post-non-tail-call stack adjustment of the form "sub // sp, sp, #offset": if ((*instruction >> 12) == 0xe24dd) { unsigned value = *instruction & 0xff; @@ -292,7 +292,7 @@ class MyArchitecture: public Architecture { virtual void nextFrame(void* start, unsigned size, unsigned footprint, void* link, bool mostRecent, - unsigned targetParameterFootprint, void** ip, + int targetParameterFootprint, void** ip, void** stack) { arm::nextFrame(&con, static_cast(start), size, footprint, link, diff --git a/src/codegen/target/powerpc/assembler.cpp b/src/codegen/target/powerpc/assembler.cpp index 9a12b84257..e884dc17bc 100644 --- a/src/codegen/target/powerpc/assembler.cpp +++ b/src/codegen/target/powerpc/assembler.cpp @@ -191,7 +191,7 @@ argumentFootprint(unsigned footprint) void nextFrame(ArchitectureContext* c UNUSED, int32_t* start, unsigned size, unsigned footprint, void* link, bool, - unsigned targetParameterFootprint, void** ip, void** stack) + int targetParameterFootprint, void** ip, void** stack) { assert(c, *ip >= start); assert(c, *ip <= start + (size / BytesPerWord)); @@ -214,7 +214,7 @@ nextFrame(ArchitectureContext* c UNUSED, int32_t* start, unsigned size, unsigned offset = footprint; - if (TailCalls) { + if (TailCalls and targetParameterFootprint >= 0) { if (argumentFootprint(targetParameterFootprint) > StackAlignmentInWords) { offset += argumentFootprint(targetParameterFootprint) - StackAlignmentInWords; @@ -391,7 +391,7 @@ class MyArchitecture: public Architecture { virtual void nextFrame(void* start, unsigned size, unsigned footprint, void* link, bool mostRecent, - unsigned targetParameterFootprint, void** ip, + int targetParameterFootprint, void** ip, void** stack) { powerpc::nextFrame(&c, static_cast(start), size, footprint, link, diff --git a/src/codegen/target/x86/assembler.cpp b/src/codegen/target/x86/assembler.cpp index c3a0e2156e..bdf4070a8c 100644 --- a/src/codegen/target/x86/assembler.cpp +++ b/src/codegen/target/x86/assembler.cpp @@ -72,7 +72,7 @@ read4(uint8_t* p) void nextFrame(ArchitectureContext* c UNUSED, uint8_t* start, unsigned size UNUSED, unsigned footprint, void*, bool mostRecent, - unsigned targetParameterFootprint, void** ip, void** stack) + int targetParameterFootprint, void** ip, void** stack) { assert(c, *ip >= start); assert(c, *ip <= start + size); @@ -114,13 +114,13 @@ nextFrame(ArchitectureContext* c UNUSED, uint8_t* start, unsigned size UNUSED, unsigned offset = footprint + FrameHeaderSize - (mostRecent ? 1 : 0); - if (TailCalls) { + if (TailCalls and targetParameterFootprint >= 0) { if (argumentFootprint(targetParameterFootprint) > StackAlignmentInWords) { offset += argumentFootprint(targetParameterFootprint) - StackAlignmentInWords; } - // check for post-non-tail-call stack adjustment of the form "add + // check for post-non-tail-call stack adjustment of the form "sub // $offset,%rsp": if (TargetBytesPerWord == 4) { if ((*instruction == 0x83 or *instruction == 0x81) @@ -141,6 +141,14 @@ nextFrame(ArchitectureContext* c UNUSED, uint8_t* start, unsigned size UNUSED, // todo: check for and handle tail calls } + + if (UseFramePointer and not mostRecent) { + assert(c, static_cast(*stack)[-1] + 1 + == static_cast(*stack) + offset); + + assert(c, static_cast(*stack)[-1][1] + == static_cast(*stack)[offset]); + } *ip = static_cast(*stack)[offset]; *stack = static_cast(*stack) + offset; @@ -369,7 +377,7 @@ class MyArchitecture: public Architecture { virtual void nextFrame(void* start, unsigned size, unsigned footprint, void* link, bool mostRecent, - unsigned targetParameterFootprint, void** ip, + int targetParameterFootprint, void** ip, void** stack) { x86::nextFrame(&c, static_cast(start), size, footprint, diff --git a/test/StackOverflow.java b/test/StackOverflow.java index c613fe5616..e25e3819eb 100644 --- a/test/StackOverflow.java +++ b/test/StackOverflow.java @@ -1,5 +1,17 @@ public class StackOverflow { + private static int add(int[] numbers, int offset, int length) { + if (length == 0) { + return 0; + } else { + return numbers[offset] + add(numbers, offset + 1, length - 1); + } + } + private static int add(int ... numbers) { + return add(numbers, 0, numbers.length); + } + private static int test1() { + add(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); return test1() + 1; }