YottaDB / YDB

Mirrored from https://gitlab.com/YottaDB/DB/YDB
Other
76 stars 37 forks source link

[#141] Fix ZSTEP OVER and ZSTEP OUTOF to work if an extrinsic function returns using QUIT @ syntax #142

Closed nars1 closed 6 years ago

nars1 commented 6 years ago

ZSTEP OVER operates (in op_zstep.c) by noting down the current $zlevel in the global variable "zstep_level" and changing the transfer table so "opp_zst_over_retarg" is invoked instead of "op_retarg" but otherwise leaves the transfer table untouched so op_linestart etc. are still executed as normal as long as nested levels of M frames are invoked. If the nested level invocation is an extrinsic function (that returns a value) "opp_zst_over_retarg" is invoked as part of returning from that level. "opp_zst_over_retarg" (in op_bkpt.s) checks if "zstep_level" is the same as frame_pointer->old_frame_pointer and if so, it calls "op_zstepret" to fix the transfer table so "op_zst_st_over" is invoked instead of "op_linestart" (and so on). That is, the ZSTEP action which was hidden during nested levels of invocations becomes active the moment the return from nested level occurs. This check did not take into account that in case of a QUIT @ usage, due to the indirection usage, there is an extra nested uncounted frame that is where the OC_RETARG opcode happens. So "opp_zst_over_retarg" gets invoked while the global variable "frame_pointer" is 2 levels deeper than "zstep_level" but one of those 2 levels is an uncounted frame. In this case the "frame_pointer->old_frame_pointer == zstep_level" check in "opp_zst_over_retarg" incorrectly decided it was not yet time to make the ZSTEP action active. This is now fixed by invoking a C helper function "op_zst_over_retarg_helper" which takes these uncounted frames into account and ensures (by adjusting "zstep_level") that "opp_zst_over_retarg" does the right thing even in this case.

A similar issue with ZSTEP OUTOF which now has "op_zstepretarg_helper" ensuring "opp_zstepretarg" does the right thing.

Since assembly modules are involved, the fix is needed separately for the x86_64 and armv7l architectures. But the more complicated part of the fix (traversing the frame_pointer linked list and checking for counted frames) was done in C helper functions to minimize assembly changes.