chicken-users
[Top][All Lists]
Advanced

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

Re: [Chicken-users] Question about gc-roots


From: Peter Bex
Subject: Re: [Chicken-users] Question about gc-roots
Date: Fri, 14 Mar 2014 22:23:20 +0100
User-agent: Mutt/1.4.2.3i

On Thu, Mar 13, 2014 at 12:44:44PM +0100, pluijzer . wrote:
> I am assigning non-immediate objects to foreign void pointers. To
> prevent them from moving during garbage collection I turn the pointer
> into a gc-root.
> 
> This works like I expect it would work, with one exception:
> 
> It seems that the finalizers of the objects assigned to the objects
> inside the gc-root get fired prematurely.
> 
> I think I'm a little difficult to follow, I'll give an example:
> 
> ----
> #>
> void* ptr;
> <#
> 
> (define init-root
>  (foreign-lambda* void ((scheme-object obj)) "
>     ptr = CHICKEN_new_gc_root();
>     CHICKEN_gc_root_set(ptr, obj);"))
> 
> (define root-ref
>   (foreign-lambda* scheme-object () "
>     C_return(CHICKEN_gc_root_ref(ptr));"))
> 
> (define (make-some-string)
>   (set-finalizer! "hello" (lambda (s) (print s ", just got freed."))))
> 
> (define-record metadata
>   data)
> 
> (init-root (make-metadata (make-some-string)))
> 
> ; prints "hello"
> (print (metadata-data (root-ref)))
> 
> ; will fire finalizer printing "hello, just got freed."
> ; I didn't expect this because there is still a refrence to the object
> inside the root.
> (gc #t)
> 
> ; prints "hello", object seems to still be around.
> (print (metadata-data (root-ref)))
> ---
> 
> Maybe I don't understand gc-roots and use them wrongly or for the
> wrong purpose. If so, would somebody kindly explain.

Hello Pluijzer,

I had a look at the GC again, and from what I can make of it, this happens
only for constants (objects that do not live in the stack or heap).  Those
don't get marked, so they appear to be dead (the GC root has no effect on
this).  I'm not sure if this is by design, and if this is a bug or not.
This is probably slightly wrong.  I've CCed Felix, maybe he can shed some
light on this.

The compiler will optimize away some calls to pure functions and replace
them by a constant at compile-time, which means even some seemingly
dynamically-allocated objects will trigger this.  You can see this in
action with the following simplified program:

-----
(define foobar
  (let ((x (string-append "some" " string")))
    (set-finalizer! x (lambda (s) (print s ", just got freed.")))))

; With -O1 or more, will fire finalizer printing "some string, just got freed."
(gc #t)

; prints "some string", object is still around.
(print foobar)
-----

If you compile the above program with -O0, it will only print
"some string", because the string-append call doesn't get optimized
away to a constant.  With -O1, it does get replaced and the GC sees
it as being available (this shows up as "folded constant expression"
when you use csc -debug o).

Now, in most normal code this won't be a problem because it only makes
sense to put finalizers on objects that need special destruction logic,
which don't tend to be constant-foldable.

Cheers,
Peter
-- 
http://www.more-magic.net



reply via email to

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