guile-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: scm_remember


From: Dirk Herrmann
Subject: Re: scm_remember
Date: Wed, 1 Nov 2000 17:00:48 +0100 (MET)

On 1 Nov 2000, Marius Vollmer wrote:

> Dirk Herrmann <address@hidden> writes:
> 
> > Hello!
> > 
> > The function scm_remember has the purpose, to protect its argument from
> > gc:
> > 
> >   chars = SCM_STRING_CHARS (str);
> >   some_syscall (chars);
> >   scm_remember (&str);
> > 
> > The call to scm_remember forces the compiler to keep the value str
> > alive until after the call to some_syscall.  Currently, scm_remember
> > expects a scm* as its parameter.  However, for the sake of keeping the
> > value alive it would suffice to pass the SCM value:
> > 
> >   chars = SCM_STRING_CHARS (str);
> >   some_syscall (chars);
> >   scm_remember (str);
> > 
> > The protection is the same,
> 
> Hmm, the former will make sure that `str' stays on the stack, and you
> can use the variable `str' to point to different SCM objects in the
> course of the function and they wil all be protected.
> 
> For example:
> 
>     SCM str;
>     char *chars = SCM_STRING_CHARS (str);
>     some_syscall (chars);
>     str = SCM_BOOL_F;
>     scm_remember (&str);
> 
> will ensure that the object originally pointed to by `str' is properly
> protected, [...]

Hmmm.  I don't think so.  Why should the original content of str be
protected in this case?  You rather protect the new content, namely #f.
In the moment when scm_remember (&str) is called, the str object already
holds the new value, and this is also obvious for the compiler.  Thus,
compiler _knows_ that &str is a pointer to the value SCM_BOOL_F.

However, certainly there _is_ a difference between the two versions.  I
will try to explain what IMO is the difference:

scm_remember (obj):  This is used to artificially extend the lifetime of
the obj for the compiler.  The compiler sees that the obj will be used as
a paramter for scm_remember and thus has keep that value up to this
call which means to store the value somewhere, maybe in a register, maybe
not.  After the call to scm_remember, the lifetime of obj ends and the
compiler is allowed to reuse the corresponding resource.

scm_remember (&obj):  Firstly, this requires the compiler to actually
store the obj in memory, to obtain the address.  Further, the compiler
must assume that scm_remember might store the address in a global variable
and thus to make the object accessible and mutable from the outside.  The
effect is, that the compiler has to keep the object alive up to the _last_
function that is called from the current scope.  Example:

  ...
  chars = SCM_STRING_CHARS (str);
  scm_remember (&str);
  foo();
  ...
  chars [0] = 'x';
  bar();
  chars [1] = 'y';
  return;

The compiler does not know what scm_remember does.  Thus the compiler
assumes, that scm_remember stores &str in a global variable.  Further, foo
and bar might access that (compiler assumed) global variable.  But, after
bar has been called, there is no function call any more in the local
scope.  Thus, the assignment to chars[1] is already insecure, since the
compiler might reuse the stack space for str immediately after bar was
called.

Thus, the implications of scm_remember (&str) are less obvious.  Even
worse, they are dependent of the compiler's knowledge.  Assume in the
above example, that bar was an inline function.  After inlining, the
compiler could see that bar does not access any global variable.  Thus,
the compiler could reduce the lifetime of str up to the call to foo.
Therefore, if bar can be inlined and does neither access global variables
nor does it call any functions, the assignment to chars[0] also becomes
insecure.  This is not good.

Best regards
Dirk




reply via email to

[Prev in Thread] Current Thread [Next in Thread]