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; }