GNU bug report logs - #42360
[feature/native-comp] miscompilation(?) of functions with non local exits

Previous Next

Package: emacs;

Reported by: Andrea Corallo <akrl <at> sdf.org>

Date: Wed, 15 Jul 2020 08:25:02 UTC

Severity: normal

Done: Andrea Corallo <akrl <at> sdf.org>

Bug is archived. No further changes may be made.

To add a comment to this bug, you must first unarchive it, by sending
a message to control AT debbugs.gnu.org, with unarchive 42360 in the body.
You can then email your comments to 42360 AT debbugs.gnu.org in the normal way.

Toggle the display of automated, internal messages from the tracker.

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to bug-gnu-emacs <at> gnu.org:
bug#42360; Package emacs. (Wed, 15 Jul 2020 08:25:02 GMT) Full text and rfc822 format available.

Acknowledgement sent to Andrea Corallo <akrl <at> sdf.org>:
New bug report received and forwarded. Copy sent to bug-gnu-emacs <at> gnu.org. (Wed, 15 Jul 2020 08:25:02 GMT) Full text and rfc822 format available.

Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Andrea Corallo <akrl <at> sdf.org>
To: bug-gnu-emacs <at> gnu.org
Cc: Eli Zaretskii <eliz <at> gnu.org>, Stefan Monnier <monnier <at> iro.umontreal.ca>
Subject: [feature/native-comp] miscompilation(?) of functions with non local
 exits
Date: Wed, 15 Jul 2020 08:24:00 +0000
Due to a recent modification native-comp is (probably?) miscompiling
lexical scope functions with non local exits if they involve code with
side effect on local variables.  Before fixing I prefer to double check
the correct behavior we want.

Considering the following piece of (lexical scoped) code:

===
(let (x)
  (ignore-errors
    (setq x t)
    (error "foo"))
  x)
===

Three options:

  1- Because setq is evaluated the expression should always evaluate to
  t.

  2- Unwinding the original state of the stack is restored, when it was
  saved 'x' was nil so the expression should evaluate to nil.

  3- This is unspecified.

The current stock implementaion does always 1 so I'm prone to just go
for it but I wanted to double check to be on the safe side.

FYI 1 implies C register variables cannot be used to implement Lisp
local variable if non local exits are present.

Thanks

  Andrea

--
akrl <at> sdf.org




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#42360; Package emacs. (Wed, 15 Jul 2020 14:26:01 GMT) Full text and rfc822 format available.

Message #8 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: Andrea Corallo <akrl <at> sdf.org>
Cc: bug-gnu-emacs <at> gnu.org, monnier <at> iro.umontreal.ca
Subject: Re: [feature/native-comp] miscompilation(?) of functions with non
 local exits
Date: Wed, 15 Jul 2020 17:25:11 +0300
> From: Andrea Corallo <akrl <at> sdf.org>
> Cc: Eli Zaretskii <eliz <at> gnu.org>, Stefan Monnier <monnier <at> iro.umontreal.ca>
> Date: Wed, 15 Jul 2020 08:24:00 +0000
> 
> ===
> (let (x)
>   (ignore-errors
>     (setq x t)
>     (error "foo"))
>   x)
> ===
> 
> Three options:
> 
>   1- Because setq is evaluated the expression should always evaluate to
>   t.
> 
>   2- Unwinding the original state of the stack is restored, when it was
>   saved 'x' was nil so the expression should evaluate to nil.
> 
>   3- This is unspecified.
> 
> The current stock implementaion does always 1 so I'm prone to just go
> for it but I wanted to double check to be on the safe side.

I tend to alternative 1 as well.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#42360; Package emacs. (Wed, 15 Jul 2020 19:18:02 GMT) Full text and rfc822 format available.

Message #11 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Stefan Monnier <monnier <at> iro.umontreal.ca>
To: Andrea Corallo <akrl <at> sdf.org>
Cc: bug-gnu-emacs <at> gnu.org, Eli Zaretskii <eliz <at> gnu.org>
Subject: Re: [feature/native-comp] miscompilation(?) of functions with non
 local exits
Date: Wed, 15 Jul 2020 15:17:27 -0400
> Three options:
>
>   1- Because setq is evaluated the expression should always evaluate to
>   t.
>
>   2- Unwinding the original state of the stack is restored, when it was
>   saved 'x' was nil so the expression should evaluate to nil.
>
>   3- This is unspecified.

Very definitely (1)!

We don't want to introduce into Elisp the kind of messy semantics you
get in C with non-volatile variables and longjmp.

> FYI 1 implies C register variables cannot be used to implement Lisp
> local variable if non local exits are present.

IIUC, the problem only occurs for those vars which have
a `condition-case` (or `unwind-protect` or `catch`) in their scope and
where the var is modified within that construct and that a non-local
exit can jump to the end of that construct after the var was thus
modified, and that the var is used after the construct.

This should be fairly rare (not sure if those cases can easily be
written differently, OTOH).    The compiler could replace those vars
by boxing them inside a cons-cell (so the register-stored C var is
immutable and contains a pointer to a cons cell which holds the real
value in the `car`), just like we do with mutated Elisp vars captured
by closures.


        Stefan





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#42360; Package emacs. (Wed, 15 Jul 2020 21:20:02 GMT) Full text and rfc822 format available.

Message #14 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Andrea Corallo <akrl <at> sdf.org>
To: Stefan Monnier <monnier <at> iro.umontreal.ca>
Cc: bug-gnu-emacs <at> gnu.org, Eli Zaretskii <eliz <at> gnu.org>
Subject: Re: [feature/native-comp] miscompilation(?) of functions with non
 local exits
Date: Wed, 15 Jul 2020 21:19:37 +0000
Stefan Monnier <monnier <at> iro.umontreal.ca> writes:

>> Three options:
>>
>>   1- Because setq is evaluated the expression should always evaluate to
>>   t.
>>
>>   2- Unwinding the original state of the stack is restored, when it was
>>   saved 'x' was nil so the expression should evaluate to nil.
>>
>>   3- This is unspecified.
>
> Very definitely (1)!

All right, I pushed a fix that restores behavior 1.

>> FYI 1 implies C register variables cannot be used to implement Lisp
>> local variable if non local exits are present.
>
> IIUC, the problem only occurs for those vars which have
> a `condition-case` (or `unwind-protect` or `catch`) in their scope and
> where the var is modified within that construct and that a non-local
> exit can jump to the end of that construct after the var was thus
> modified, and that the var is used after the construct.

Correct.  If the compiler keep these variables in the stack then it's
all fine because setjump will restore SP and inside the stack you'll
find the most updated value.  On the contrary if the variable was kept
in a register then its updated value may be lost if the reg is callee
saved.

> This should be fairly rare (not sure if those cases can easily be
> written differently, OTOH).

The case I've encountered is `truncate-string-to-width'.

> The compiler could replace those vars
> by boxing them inside a cons-cell (so the register-stored C var is
> immutable and contains a pointer to a cons cell which holds the real
> value in the `car`), just like we do with mutated Elisp vars captured
> by closures.

What I pushed now is (for functions with non locals) just to keep stored
all local vars in an array (as the bytecompiler does).  I added note and
we should be able to implement something more selective as suggested.
Either adding an indirection or marking the sensitive variables as
volatile.

Thanks both for the feedback.

  Andrea

-- 
akrl <at> sdf.org




Reply sent to Andrea Corallo <akrl <at> sdf.org>:
You have taken responsibility. (Thu, 16 Jul 2020 19:48:02 GMT) Full text and rfc822 format available.

Notification sent to Andrea Corallo <akrl <at> sdf.org>:
bug acknowledged by developer. (Thu, 16 Jul 2020 19:48:02 GMT) Full text and rfc822 format available.

Message #19 received at 42360-done <at> debbugs.gnu.org (full text, mbox):

From: Andrea Corallo <akrl <at> sdf.org>
To: 42360-done <at> debbugs.gnu.org
Cc: eliz <at> gnu.org, Stefan Monnier <monnier <at> iro.umontreal.ca>
Subject: Re: bug#42360: [feature/native-comp] miscompilation(?) of functions
 with non local exits
Date: Thu, 16 Jul 2020 19:47:30 +0000
Right I think we can close this.

Thanks

  Andrea

-- 
akrl <at> sdf.org




bug archived. Request was from Debbugs Internal Request <help-debbugs <at> gnu.org> to internal_control <at> debbugs.gnu.org. (Fri, 14 Aug 2020 11:24:06 GMT) Full text and rfc822 format available.

This bug report was last modified 3 years and 248 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.