On Fri, 04 Sep 2009 00:44:35 EDT erik quanstrom <quans...@quanstro.net>  wrote:
> > > that sucker is on the stack.  by-by no-execute stack.

I don't think so. See below.

> > > how does it get to the stack?  is it just copied from
> > > the text segment or is it compiled at run time?
> > >
> > 
> > I don't think I posted the whole code, so that's my bad.  The X was on the
> > stack to begin with as the first X was an automatic variable in a function.
> >  I'd be a little surprised to find an automatic variable in the text
> > segment, but perhaps that's just my not remembering things properly.
> >  (didn't mean that tongue in cheek, I don't think about that stuff much
> > these days, as I've spent the last year or so doing Erlang and Haskell.)
> 
> it is the block itself that apple claims is on the stacp
> (your grand centeral reference, p. 38).  and i wonder
> how it gets there.  is it just copied from the text segment?
> that seems kind of pointless.  why not just execute it
> from the text segment?  or is it modified (compiled?)
> at run time?

[Note: I am simply guessing and have no idea how they
 actually do this but this model seems workable]

Consider this example:

    int foo(int a) {
        __block int b = 0;
        int (^g()) = ^{ return a + ++b; }
                ...
        return g() + g();
    }


My guess is the above will be translated to something like this:

    struct anon1 {
        int             (*f)(struct anon1*);
        const int       a;
        int *const      bp;
    };
    int anon1_f(struct anon1* x) {
        return x->a + ++(*x->bp);
    }
    int foo(int a) {
        int *bp = malloc(sizeof *bp); // not quite. see the correction below
        *bp = 0;
        struct anon1 _anon = { &anon1_f, a, &b };
        struct anon1* g = &_anon;
                ...
        return g->f(&_anon) + g->f(&_anon);
    }

As you can see, _anon will disappear when foo() is exited.
But if you were to Block_copy() _anon, it will be allocated
on the heap and a ptr to it returned. Now you do have
everything needed to call this anon function even after
returning from foo().  &_anon can also be passed to another
thread etc. with no problem.

Most likely __block variables are allocated on the heap and
ref counted.  Ref count is decremented on exit from the
lexical scope where a __block var is defined.  Block_copy()
increments refcount of every __block var referenced by the
block, Block_release() decrements it.

So this is basically a function closure. They seem to have
very carefully navigated around C's semantic sand bars.

Reply via email to