LLVM tail calling bug

jerry-core/ecma/operations/ecma-proxy-object.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/jerry-core/ecma/operations/ecma-proxy-object.c b/jerry-core/ecma/operations/ecma-proxy-object.c
index c5d299c6..77aed25c 100644
--- a/jerry-core/ecma/operations/ecma-proxy-object.c
+++ b/jerry-core/ecma/operations/ecma-proxy-object.c
@@ -1108,7 +1108,9 @@ ecma_proxy_object_get (ecma_object_t *obj_p, /**< proxy object */
if (ecma_is_value_undefined (trap))
{
ecma_object_t *target_obj_p = ecma_get_object_from_value (proxy_obj_p->target);
- return ecma_op_object_get_with_receiver (target_obj_p, prop_name_p, receiver);
+ ecma_value_t value = ecma_op_object_get_with_receiver (target_obj_p, prop_name_p, receiver);
+ fflush (stdout);
+ return value;
}

ecma_object_t *func_obj_p = ecma_get_object_from_value (trap);

In which condition, ecma_op_object_get_with_receiver tail calling will not increase the stack-size?
I have a test-case that cause infinite loop, because that in normal conition, it’s expect to raise an stack-exceed error but
now with llvm-compiled release build binary, it’s turn out to be infinite loop because ecma_op_object_get_with_receiver
will not increase the stack size anymore, once ecma_op_object_get_with_receiver getting called, it’s returned to the previous stack position。
Reproduced on OSX/Ubuntu 20.04

Stack-trace-base

jerry!ecma_proxy_object_get (\Users\lygstate\work\typescript\jerryscript\jerry-core\ecma\operations\ecma-proxy-object.c:1111)
jerry!ecma_op_object_get_with_receiver (\Users\lygstate\work\typescript\jerryscript\jerry-core\ecma\operations\ecma-objects.c:790)
jerry!ecma_op_object_get (\Users\lygstate\work\typescript\jerryscript\jerry-core\ecma\operations\ecma-objects.c:763)
jerry!vm_op_get_value (\Users\lygstate\work\typescript\jerryscript\jerry-core\vm\vm.c:114)
jerry!vm_loop (\Users\lygstate\work\typescript\jerryscript\jerry-core\vm\vm.c:2799)
jerry!vm_execute (\Users\lygstate\work\typescript\jerryscript\jerry-core\vm\vm.c:4939)
jerry!vm_run (\Users\lygstate\work\typescript\jerryscript\jerry-core\vm\vm.c:5046)
jerry!vm_run_global (\Users\lygstate\work\typescript\jerryscript\jerry-core\vm\vm.c:328)
jerry!jerry_run (\Users\lygstate\work\typescript\jerryscript\jerry-core\api\jerry.c:671)
jerry!main (\Users\lygstate\work\typescript\jerryscript\jerry-main\main-unix.c:156)
libdyld.dylib!start (Unknown Source:0)
libdyld.dylib!start (Unknown Source:0)

stack-trace-new, it’s hope ecma_op_object_get_with_receiver to deeper, but turn out to step-back.

jerry!ecma_op_object_get_with_receiver (\Users\lygstate\work\typescript\jerryscript\jerry-core\ecma\operations\ecma-objects.c:784)
jerry!ecma_op_object_get (\Users\lygstate\work\typescript\jerryscript\jerry-core\ecma\operations\ecma-objects.c:763)
jerry!vm_op_get_value (\Users\lygstate\work\typescript\jerryscript\jerry-core\vm\vm.c:114)
jerry!vm_loop (\Users\lygstate\work\typescript\jerryscript\jerry-core\vm\vm.c:2799)
jerry!vm_execute (\Users\lygstate\work\typescript\jerryscript\jerry-core\vm\vm.c:4939)
jerry!vm_run (\Users\lygstate\work\typescript\jerryscript\jerry-core\vm\vm.c:5046)
jerry!vm_run_global (\Users\lygstate\work\typescript\jerryscript\jerry-core\vm\vm.c:328)
jerry!jerry_run (\Users\lygstate\work\typescript\jerryscript\jerry-core\api\jerry.c:671)
jerry!main (\Users\lygstate\work\typescript\jerryscript\jerry-main\main-unix.c:156)
libdyld.dylib!start (Unknown Source:0)
libdyld.dylib!start (Unknown Source:0)

Same clang , build it with debug flag, the issue gone. I am wonder if there is a misoptimization here

The c code
https://gist.github.com/lygstate/b554e74a22353d50a24240128f875474

The full source tree
https://github.com/lygstate/jerryscript/tree/osx-clang-bug

When you say "build it with the debug flag"could you be more precise? What was the exact/complete compilation command line you used for the failing and succeeding case?

In any case, it sounds like maybe you build an unoptimized build and the test passed (because tail callingwasn’t done, the stack grew, and the overflow terminated the process as expected) and an optimized build where tail calling was done and the stack never overflowed/process never crashed.

That sounds like expected/reasonable/correct behavior to me - and that the test is flawed & shouldn’t be expecting to be guaranteed that the stack will overflow in this case.

When you say "build it with the debug flag"could you be more precise? What was the exact/complete compilation command line you used for the failing and succeeding case?

In any case, it sounds like maybe you build an unoptimized build and the test passed (because tail callingwasn’t done, the stack grew, and the overflow terminated the process as expected) and an optimized build where tail calling was done and the stack never overflowed/process never crashed.

That sounds like expected/reasonable/correct behavior to me - and that the test is flawed & shouldn’t be expecting to be guaranteed that the stack will overflow in this case.
Hi, this is a javascript engine, we wanna make sure the compiler won’t do tail calling optimization for these functions, any option to do that?

When you say "build it with the debug flag"could you be more precise? What was the exact/complete compilation command line you used for the failing and succeeding case?

In any case, it sounds like maybe you build an unoptimized build and the test passed (because tail callingwasn’t done, the stack grew, and the overflow terminated the process as expected) and an optimized build where tail calling was done and the stack never overflowed/process never crashed.

That sounds like expected/reasonable/correct behavior to me - and that the test is flawed & shouldn’t be expecting to be guaranteed that the stack will overflow in this case.
Hi, this is a javascript engine, we wanna make sure the compiler won’t do tail calling optimization for these functions, any option to do that?

Not sure why you’d want to avoid tail call optimizations, but if you want to you could use this as reference/inspiration: https://chromium.googlesource.com/external/github.com/abseil/abseil-cpp/+/HEAD/absl/base/optimization.h#29

Thanks a lot, know how to do that.