Closed KenDickey closed 8 years ago
Indeed, this is true even in v0.98. We configure the build with EXPLICIT_DIVZ_CHECK and the test at the start of mc_div() (generated from arithmetic.mac) therefore invokes mc_exception() as it should, but that call returns and we fall into the division anyway, generating the fault. So something is wonky with the exception handling machinery (and the test suite needs another test :)
Changeset 10eb0f9c2bc42d590a9d8571175170764af1a6f2 added tests that should help to debug this.
The Fence/ARM version contains nine calls to the C function mc_exception
. Four of those nine calls are in the millicode procedures fmc_global_exception
, fmc_invoke_exception
, fmc_global_invoke_exception
, and fmc_argc_exception
; those four calls are working fine.
The other five, all within src/Rts/Shared/arithmetic.c
, call mc_exception
in response to a divide-by-zero in the code for /
, quotient
, and remainder
.
The Fence/ARM version of mc_exception
always returns. That's okay when it's returning to Scheme code, because mc_exception
calls mc_scheme_callout
to set up the registers appropriately for a return to Scheme code.
That's not okay when mc_exception
is returning to the C code in arithmetic.c
. We need a longjmp
in there somewhere to avoid returning to code that will divide by zero.
The IAssassin version of mc_scheme_callout
performs a longjmp
if its continuation argument k
is zero. In IAssassin, I believe that argument will be zero if and only if mc_scheme_callout
was called from mc_exception
, so k
is doing double duty as a flag to tell mc_scheme_callout
whether it needs to do a longjmp
.
The Fence/ARM version never does a longjmp
, and it doesn't look as though the k
hack will be easy to restore because the Fence/ARM version always passes zero for that argument when calling from Scheme to millicode, relying on availability of the return address in the globals area.
So I know what the problem is, but I haven't yet decided on the best way to fix it. Changing the Fence/ARM version to pass a return address would make it more like IAssassin, but that's just a hack and I'm nervous about the number of changes that would be required. Adding an extra argument to mc_scheme_callout
to tell it whether to do a longjmp
would be less of a hack, but it would require changes to code shared by all versions of Larceny, which makes me even more nervous.
Fixed by changeset 5d76120555c7fe2bbecd55920a3aa90bb3415960