unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* please help concerning specpdl
@ 2010-12-04  5:33 Alin Soare
  2010-12-06 16:22 ` Davis Herring
  0 siblings, 1 reply; 5+ messages in thread
From: Alin Soare @ 2010-12-04  5:33 UTC (permalink / raw)
  To: Emacs Dev

[-- Attachment #1: Type: text/plain, Size: 535 bytes --]

Many functions in emacs contain the sequence
{
count = SPECPDL_INDEX ();
record_unwind_protect
val = Fprogn (args);
return unbind_to (count, val);
}


like the  function attached below,

Can you explain me the logic of specpdl please ?



DEFUN ("save-current-buffer", Fsave_current_buffer, Ssave_current_buffer, 0,
UNEVALLED, 0,
....
  (Lisp_Object args)
{
  Lisp_Object val;
  int count = SPECPDL_INDEX ();

  record_unwind_protect (set_buffer_if_live, Fcurrent_buffer ());

  val = Fprogn (args);
  return unbind_to (count, val);
}

[-- Attachment #2: Type: text/html, Size: 656 bytes --]

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: please help concerning specpdl
  2010-12-04  5:33 please help concerning specpdl Alin Soare
@ 2010-12-06 16:22 ` Davis Herring
  2010-12-14 21:25   ` Alin Soare
  0 siblings, 1 reply; 5+ messages in thread
From: Davis Herring @ 2010-12-06 16:22 UTC (permalink / raw)
  To: Alin Soare; +Cc: Emacs Dev

> count = SPECPDL_INDEX ();
> record_unwind_protect
> val = Fprogn (args);
> return unbind_to (count, val);

> Can you explain me the logic of specpdl please ?

The specpdl contains information needed to remove variable bindings and
provide other services that are guaranteed even in the case of abnormal
exit.  Abnormal exits operate by calling longjmp(3), so there's no
guaranteed chance to perform cleanup in the normal flow of execution.  But
the function that calls longjmp(3) (`unwind_to_catch') first peruses the
specpdl and handles its elements appropriately, so the guaranteed
operations happen.  The actual unwinding is done by `unbind_to', so if the
body exits normally, we just call that to perform the unwinding operations
without longjmp(3).

So: the count identifies how far to unwind in case of normal exit (in case
of abnormal exit, we'll unwind farther anyway, so we don't need `count'). 
The `record_unwind_protect' registers something to do at unwind-time, and
then `unbind_to' performs it unless `unwind_to_catch' does.  `val' is
passed to `unbind_to' for GC reasons, I believe.

Davis

-- 
This product is sold by volume, not by mass.  If it appears too dense or
too sparse, it is because mass-energy conversion has occurred during
shipping.



^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: please help concerning specpdl
  2010-12-06 16:22 ` Davis Herring
@ 2010-12-14 21:25   ` Alin Soare
  2010-12-15  0:14     ` Davis Herring
  0 siblings, 1 reply; 5+ messages in thread
From: Alin Soare @ 2010-12-14 21:25 UTC (permalink / raw)
  To: herring; +Cc: Emacs Dev

[-- Attachment #1: Type: text/plain, Size: 2324 bytes --]

> > count = SPECPDL_INDEX ();
> > record_unwind_protect
> > val = Fprogn (args);
> > return unbind_to (count, val);
>
> > Can you explain me the logic of specpdl please ?
>
> The specpdl contains information needed to remove variable bindings and
> provide other services that are guaranteed even in the case of abnormal
> exit.  Abnormal exits operate by calling longjmp(3), so there's no
> guaranteed chance to perform cleanup in the normal flow of execution.  But
> the function that calls longjmp(3) (`unwind_to_catch') first peruses the
> specpdl and handles its elements appropriately, so the guaranteed
> operations happen.  The actual unwinding is done by `unbind_to', so if the
> body exits normally, we just call that to perform the unwinding operations
> without longjmp(3).
>

I think I understand the analogy with longjmp. It is a stack of Lisp
Objects, and this stack is used by C code to protect against errors in lisp
interpreter.

The variables defined by let are memorized in this stack using SAFE_ALLOCA.

Why let-binding-variables are memorized exactly here and not elsewhere ?

On the other hand, the macro SAFE_ALLOCA is defined as

do{
}while (0)

why the do-while is good in this case, and not simply brackets?



> So: the count identifies how far to unwind in case of normal exit (in case
> of abnormal exit, we'll unwind farther anyway, so we don't need `count').
> The `record_unwind_protect' registers something to do at unwind-time, and
> then `unbind_to' performs it unless `unwind_to_catch' does.  `val' is
> passed to `unbind_to' for GC reasons, I believe.
>

I see that inside unbind_to, the symbols are unbounded 1 by one. Why the
specpdl_ptr is not decremented directly with count ?

while (specpdl_ptr != specpdl + count)

Probably because unbind_to is called from lisp code by (throw 'symbol
value), and specpdl_ptr must decrement 1 by 1 until the 'symbol is dound on
the stack ?

Apart from (throw ... ), is which other situation unbind_to is called ?


I see that GCPROx macros are used to protect the variables of type Lisp
Object on the stack of C code (that the compiler creates), not to protect
the lisp objects in specpdl. The GCPRO protection is against the algorthm of
conservative stack. Am I right ?


Sorry, I think I understand something, but I am far from enough.


Alin.

[-- Attachment #2: Type: text/html, Size: 2983 bytes --]

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: please help concerning specpdl
  2010-12-14 21:25   ` Alin Soare
@ 2010-12-15  0:14     ` Davis Herring
  2010-12-15  0:53       ` Ken Raeburn
  0 siblings, 1 reply; 5+ messages in thread
From: Davis Herring @ 2010-12-15  0:14 UTC (permalink / raw)
  To: Alin Soare; +Cc: Emacs Dev

> Why let-binding-variables are memorized exactly here and not elsewhere ?

Flet memorizes their old values on the stack; when it returns (or
otherwise is exited), the old values are copied back, so they can't be
needed beyond the lifetime of that stack frame.

> why the do-while is good in this case, and not simply brackets?

So that the whole thing is one statement that needs a ;, just like a
normal function call.  If it were brackets, you couldn't do

if(x) SAFE_ALLOCA(...);
else y=x;

> I see that inside unbind_to, the symbols are unbounded 1 by one. Why the
> specpdl_ptr is not decremented directly with count ?

Because you need to do something with each record: restore old values for
symbols, call functions registered with record_unwind_protect(), etc.

> Probably because unbind_to is called from lisp code by (throw 'symbol
> value), and specpdl_ptr must decrement 1 by 1 until the 'symbol is dound
> on the stack ?

catch-tags are searched separately: see struct catchtag.

> Apart from (throw ... ), is which other situation unbind_to is called ?

The other important one is Fsignal (quit and other errors).

> I see that GCPROx macros are used to protect the variables of type Lisp
> Object on the stack of C code (that the compiler creates), not to protect
> the lisp objects in specpdl. The GCPRO protection is against the algorthm
> of conservative stack. Am I right ?

I believe the GCPRO draws the attention of the stack checker to those Lisp
objects to make sure that they're not collected.

Davis

-- 
This product is sold by volume, not by mass.  If it appears too dense or
too sparse, it is because mass-energy conversion has occurred during
shipping.



^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: please help concerning specpdl
  2010-12-15  0:14     ` Davis Herring
@ 2010-12-15  0:53       ` Ken Raeburn
  0 siblings, 0 replies; 5+ messages in thread
From: Ken Raeburn @ 2010-12-15  0:53 UTC (permalink / raw)
  To: herring; +Cc: Alin Soare, Emacs Dev

On Dec 14, 2010, at 19:14, Davis Herring wrote:
>> I see that GCPROx macros are used to protect the variables of type Lisp
>> Object on the stack of C code (that the compiler creates), not to protect
>> the lisp objects in specpdl. The GCPRO protection is against the algorthm
>> of conservative stack. Am I right ?
> 
> I believe the GCPRO draws the attention of the stack checker to those Lisp
> objects to make sure that they're not collected.

The Lisp engine and the garbage collection code have undergone some revision over the years, and support a few different configurations based on the machine architecture and operating system support.  See, for example, the comment discussing GC_MARK_STACK in lisp.h.  GCPRO macros are used to keep track of Lisp_Object variables on the C stack in case conservative stack scanning is not used.  If conservative stack scanning is used, you can make GCPRO macros be no-ops, or you can instrument them to compare the effectiveness of the two techniques.

But in terms of writing C code, you should assume that the GCPRO machinery is required.

(Well, that's not 100% true.  If any code path that can result in the garbage collector being called either doesn't care about a particular object any more, or can guarantee that the object will be visible to the garbage collector through some other path, then it needn't be recorded with GCPRO.  But it's probably better to be conservative if you're not completely certain.)

Ken


^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2010-12-15  0:53 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-12-04  5:33 please help concerning specpdl Alin Soare
2010-12-06 16:22 ` Davis Herring
2010-12-14 21:25   ` Alin Soare
2010-12-15  0:14     ` Davis Herring
2010-12-15  0:53       ` Ken Raeburn

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).