<?xml version="1.0" encoding="UTF-8"?><!-- generator="wordpress/1.5" -->
<rss version="2.0" 
	xmlns:content="http://purl.org/rss/1.0/modules/content/">
<channel>
	<title>Comments on: Nest</title>
	<link>http://ridiculousfish.com/blog/archives/2006/02/05/nest/</link>
	<description>serious code</description>
	<pubDate>Wed, 20 Aug 2008 12:51:28 +0000</pubDate>
	<generator>http://wordpress.org/?v=1.5</generator>

	<item>
		<title>by: Simone Manganelli</title>
		<link>http://ridiculousfish.com/blog/archives/2006/02/05/nest/#comment-520</link>
		<pubDate>Sun, 05 Feb 2006 00:37:10 +0000</pubDate>
		<guid>http://ridiculousfish.com/blog/archives/2006/02/05/nest/#comment-520</guid>
					<description>I have got to say... though your entries are exceedingly technical, and though you've only written a single-digit number of entries, I really enjoy reading your weblog.  I learn new things every single entry, and even though I may not understand all of it, it still rocks.  (I never knew about nested functions, but I guess it doesn't matter anymore since they're not supported anymore. :) )

Keep these entries coming, even if they only come around once a month. :D

-- Simone</description>
		<content:encoded><![CDATA[	<p>I have got to say... though your entries are exceedingly technical, and though you&#8217;ve only written a single-digit number of entries, I really enjoy reading your weblog.  I learn new things every single entry, and even though I may not understand all of it, it still rocks.  (I never knew about nested functions, but I guess it doesn&#8217;t matter anymore since they&#8217;re not supported anymore. :) )</p>
	<p>Keep these entries coming, even if they only come around once a month. :D</p>
	<p>&#8212; Simone
</p>
]]></content:encoded>
				</item>
	<item>
		<title>by: Nevyn</title>
		<link>http://ridiculousfish.com/blog/archives/2006/02/05/nest/#comment-521</link>
		<pubDate>Sun, 05 Feb 2006 01:14:23 +0000</pubDate>
		<guid>http://ridiculousfish.com/blog/archives/2006/02/05/nest/#comment-521</guid>
					<description>I've just taken a course in compiler technology (rough translation from the Swedish name...). Our teacher worked for a company that made pretty much the only Simula compiler in the world back in the days. (Which he always was very proud of, and he made very sure that everyone knew how much Simula was superior to C).

Anyhow, the way he taught us compilers, the... *thinks a bit* ... activation record (header data for every stackable or heapable thing) for a function/block instance kept two pointers: one to the dynamically surrounding block, and one for the statically surrounding block. For example, qsort's statical father for the above example would be the global scope, while the dynamical father would be the block of sort_ints(). Comparison function would have sort_ints() as static father, and qsort as dynamical father.

This way, nested functions would be a piece of cake. comparison_function would be invisible in the global scope, and it could access any data in its statically surrounding block (sort_ints) through the static father pointer.

The theory of the insides of his compilers always looked so clean... No need for runtime generation of executable kludges!</description>
		<content:encoded><![CDATA[	<p>I&#8217;ve just taken a course in compiler technology (rough translation from the Swedish name...). Our teacher worked for a company that made pretty much the only Simula compiler in the world back in the days. (Which he always was very proud of, and he made very sure that everyone knew how much Simula was superior to C).</p>
	<p>Anyhow, the way he taught us compilers, the... *thinks a bit* ... activation record (header data for every stackable or heapable thing) for a function/block instance kept two pointers: one to the dynamically surrounding block, and one for the statically surrounding block. For example, qsort&#8217;s statical father for the above example would be the global scope, while the dynamical father would be the block of sort_ints(). Comparison function would have sort_ints() as static father, and qsort as dynamical father.</p>
	<p>This way, nested functions would be a piece of cake. comparison_function would be invisible in the global scope, and it could access any data in its statically surrounding block (sort_ints) through the static father pointer.</p>
	<p>The theory of the insides of his compilers always looked so clean... No need for runtime generation of executable kludges!
</p>
]]></content:encoded>
				</item>
	<item>
		<title>by: Michel Fortin</title>
		<link>http://ridiculousfish.com/blog/archives/2006/02/05/nest/#comment-522</link>
		<pubDate>Sun, 05 Feb 2006 08:42:47 +0000</pubDate>
		<guid>http://ridiculousfish.com/blog/archives/2006/02/05/nest/#comment-522</guid>
					<description>That was very interesting. I did not know GCC had support for nested functions, but I remember using them all the time in Turbo Pascal many years ago.

So if I follow you correctly, this could mean that in a future version of Mac OS X nested functions in other compiled programming languages (like Pascal) may stop working?</description>
		<content:encoded><![CDATA[	<p>That was very interesting. I did not know GCC had support for nested functions, but I remember using them all the time in Turbo Pascal many years ago.</p>
	<p>So if I follow you correctly, this could mean that in a future version of Mac OS X nested functions in other compiled programming languages (like Pascal) may stop working?
</p>
]]></content:encoded>
				</item>
	<item>
		<title>by: Aaron Jacobs</title>
		<link>http://ridiculousfish.com/blog/archives/2006/02/05/nest/#comment-523</link>
		<pubDate>Sun, 05 Feb 2006 08:59:54 +0000</pubDate>
		<guid>http://ridiculousfish.com/blog/archives/2006/02/05/nest/#comment-523</guid>
					<description>I'd like to agree with Simone and say that I really really enjoy your posts, *because* they are extremely technical.  Post more often!</description>
		<content:encoded><![CDATA[	<p>I&#8217;d like to agree with Simone and say that I really really enjoy your posts, *because* they are extremely technical.  Post more often!
</p>
]]></content:encoded>
				</item>
	<item>
		<title>by: corbin</title>
		<link>http://ridiculousfish.com/blog/archives/2006/02/05/nest/#comment-525</link>
		<pubDate>Sun, 05 Feb 2006 10:45:25 +0000</pubDate>
		<guid>http://ridiculousfish.com/blog/archives/2006/02/05/nest/#comment-525</guid>
					<description>Pascal and Delphi supports nested functions on Intel (obviously). But, it's been a while since I've filtered through the dcc (delphi command compiler) source, so I don't quite remember how they did it. I'll have to fire up my windows machine some day and take a look at the x86 gened from a nested function.

-corbin</description>
		<content:encoded><![CDATA[	<p>Pascal and Delphi supports nested functions on Intel (obviously). But, it&#8217;s been a while since I&#8217;ve filtered through the dcc (delphi command compiler) source, so I don&#8217;t quite remember how they did it. I&#8217;ll have to fire up my windows machine some day and take a look at the x86 gened from a nested function.</p>
	<p>-corbin
</p>
]]></content:encoded>
				</item>
	<item>
		<title>by: wrf3</title>
		<link>http://ridiculousfish.com/blog/archives/2006/02/05/nest/#comment-526</link>
		<pubDate>Sun, 05 Feb 2006 12:22:56 +0000</pubDate>
		<guid>http://ridiculousfish.com/blog/archives/2006/02/05/nest/#comment-526</guid>
					<description>Pascal supports nested functions by the design of the language.  So nested functions will always work in Pascal.  Nested functions in C is a non-standard addition and this particular implementation was a &quot;hack&quot; to get it working.</description>
		<content:encoded><![CDATA[	<p>Pascal supports nested functions by the design of the language.  So nested functions will always work in Pascal.  Nested functions in C is a non-standard addition and this particular implementation was a &#8220;hack&#8221; to get it working.
</p>
]]></content:encoded>
				</item>
	<item>
		<title>by: Eric Albert</title>
		<link>http://ridiculousfish.com/blog/archives/2006/02/05/nest/#comment-527</link>
		<pubDate>Sun, 05 Feb 2006 12:27:46 +0000</pubDate>
		<guid>http://ridiculousfish.com/blog/archives/2006/02/05/nest/#comment-527</guid>
					<description>In my experience, other compilers implement nested functions via the same way gcc does it for C -- writing trampoline code onto the stack and executing it.  This wasn't a problem until fairly recently, since there was no such thing as disabling stack execution.

On processors which support disabling stack execution (like the Core Duo), your code can modify memory permission on a per-page basis.  For example, you could write this trampoline and then use vm_protect to make the page containing the trampoline executable.  Of course, since the trampoline is smaller than a page you'd also be making some code around it executable.  The way to avoid this is to allocate a page-sized block on the heap for the trampoline, then make it executable and non-writable.

I'd love to see a GCC patch to do this for trampolines.  It'd make -fnested-functions safe, whereas the current implementation turns off stack protection for the entire process.</description>
		<content:encoded><![CDATA[	<p>In my experience, other compilers implement nested functions via the same way gcc does it for C &#8212; writing trampoline code onto the stack and executing it.  This wasn&#8217;t a problem until fairly recently, since there was no such thing as disabling stack execution.</p>
	<p>On processors which support disabling stack execution (like the Core Duo), your code can modify memory permission on a per-page basis.  For example, you could write this trampoline and then use vm_protect to make the page containing the trampoline executable.  Of course, since the trampoline is smaller than a page you&#8217;d also be making some code around it executable.  The way to avoid this is to allocate a page-sized block on the heap for the trampoline, then make it executable and non-writable.</p>
	<p>I&#8217;d love to see a GCC patch to do this for trampolines.  It&#8217;d make -fnested-functions safe, whereas the current implementation turns off stack protection for the entire process.
</p>
]]></content:encoded>
				</item>
	<item>
		<title>by: Todd Larason</title>
		<link>http://ridiculousfish.com/blog/archives/2006/02/05/nest/#comment-528</link>
		<pubDate>Sun, 05 Feb 2006 20:06:09 +0000</pubDate>
		<guid>http://ridiculousfish.com/blog/archives/2006/02/05/nest/#comment-528</guid>
					<description>http://www.gnu-pascal.de/crystal/gpc/en/mail13020.html is interesting: the GNU Pascal people seem to be considering at least three different solutions.

One of these is trampolines, just as discussed here.  It has the advantage of allowing interfacing with C and other bare-metal languages.

Another is 'descriptors', which seem to be an AIX thing and which I don't understand.

A third is 'fat pointers'.  I think the idea here is that a pointer to a function is actually two pointers: a pointer to the code, and a pointer to the stack frame to use for its lexical scope.  It's not obvious to me whether that would affect how every function is called, or if it could be limited to functions called through function pointers.  It would also have the weird side effect of making function pointers twice as big as data pointers; would that be within the C spec?  Even if so, it would break a lot of peoples' assumptions.</description>
		<content:encoded><![CDATA[	<p><a href='http://www.gnu-pascal.de/crystal/gpc/en/mail13020.html' rel='nofollow'>http://www.gnu-pascal.de/crystal/gpc/en/mail13020.html</a> is interesting: the GNU Pascal people seem to be considering at least three different solutions.</p>
	<p>One of these is trampolines, just as discussed here.  It has the advantage of allowing interfacing with C and other bare-metal languages.</p>
	<p>Another is &#8216;descriptors&#8217;, which seem to be an AIX thing and which I don&#8217;t understand.</p>
	<p>A third is &#8216;fat pointers&#8217;.  I think the idea here is that a pointer to a function is actually two pointers: a pointer to the code, and a pointer to the stack frame to use for its lexical scope.  It&#8217;s not obvious to me whether that would affect how every function is called, or if it could be limited to functions called through function pointers.  It would also have the weird side effect of making function pointers twice as big as data pointers; would that be within the C spec?  Even if so, it would break a lot of peoples&#8217; assumptions.
</p>
]]></content:encoded>
				</item>
	<item>
		<title>by: Jens Ayton</title>
		<link>http://ridiculousfish.com/blog/archives/2006/02/05/nest/#comment-529</link>
		<pubDate>Mon, 06 Feb 2006 08:18:05 +0000</pubDate>
		<guid>http://ridiculousfish.com/blog/archives/2006/02/05/nest/#comment-529</guid>
					<description>The old Mac OS PEF (Prefered Executable Format, oh the irony) calling conventions, based on the reccomended conventions for PowerPCs, used a form of fat pointer called a transition vector (Tvector). This consisted of a pointer to the in-memory address of the function and a pointer to the table of contents of the function’s code fragment (used to look up globals). Every cross-fragment function call or pointer-based function call went through glue code which loaded the TOC pointer into RTOC (R2, IIRC), loaded the address of the Tvector into R12 and then called the function.

Function pointers were implemented as pointers to the Tvector, and a function pointer call (*Ptr)(foo) would be treated by calling the equivalent of __ptr_glue(Ptr, foo). (In answer to the question about the C spec: pointers may be different sizes, as long as void * is the size of the biggest pointer type; but this indirection makes it a non-issue.)

Normally a Tvector would just be two 32-bit words in the code fragment’s data section. However, the fact that the address of the Tvector was put in a register before the call meant that the Tvector could contain additionall arbitrary fields, and as the Tvector contained no executable code it could easily be built on the stack, even with protection. A nested function code would then generate code along these lines:

typedef struct { void *entryPoint, *TOC; } TVector;
typedef struct { void *entryPoint, *TOC; char *parentStack; } NestTVector;

void outer_function(void) {
    int x = 0;
    
    TVector tv_inner_function;
    NestTVector tvn_inner_function;
    
    tv_inner_function = (TVector *)&amp;amp;__outer_function__inner_function;
    tvn_inner_function.entryPoint = tv_inner_function.entryPoint;
    tvn_inner_function.TOC = GetRTOC();
    tvn_inner_function.stack = GetStackPointer();
    
    extern_function(inner_function);
}


void __outer_function__inner_function(void) {
    NestTVector *tvn_inner_function;
    tvn_inner_function = &amp;amp;GetR12();
    
    *(int *)(tvn_inner_function.parentStack + offsetForX)++;
}
</description>
		<content:encoded><![CDATA[	<p>The old Mac OS PEF (Prefered Executable Format, oh the irony) calling conventions, based on the reccomended conventions for PowerPCs, used a form of fat pointer called a transition vector (Tvector). This consisted of a pointer to the in-memory address of the function and a pointer to the table of contents of the function’s code fragment (used to look up globals). Every cross-fragment function call or pointer-based function call went through glue code which loaded the TOC pointer into RTOC (R2, IIRC), loaded the address of the Tvector into R12 and then called the function.</p>
	<p>Function pointers were implemented as pointers to the Tvector, and a function pointer call (*Ptr)(foo) would be treated by calling the equivalent of __ptr_glue(Ptr, foo). (In answer to the question about the C spec: pointers may be different sizes, as long as void * is the size of the biggest pointer type; but this indirection makes it a non-issue.)</p>
	<p>Normally a Tvector would just be two 32-bit words in the code fragment’s data section. However, the fact that the address of the Tvector was put in a register before the call meant that the Tvector could contain additionall arbitrary fields, and as the Tvector contained no executable code it could easily be built on the stack, even with protection. A nested function code would then generate code along these lines:</p>
	<p>typedef struct { void *entryPoint, *TOC; } TVector;<br />
typedef struct { void *entryPoint, *TOC; char *parentStack; } NestTVector;</p>
	<p>void outer_function(void) {<br />
    int x = 0;</p>
	<p>    TVector tv_inner_function;<br />
    NestTVector tvn_inner_function;</p>
	<p>    tv_inner_function = (TVector *)&amp;__outer_function__inner_function;<br />
    tvn_inner_function.entryPoint = tv_inner_function.entryPoint;<br />
    tvn_inner_function.TOC = GetRTOC();<br />
    tvn_inner_function.stack = GetStackPointer();</p>
	<p>    extern_function(inner_function);<br />
}</p>
	<p>void __outer_function__inner_function(void) {<br />
    NestTVector *tvn_inner_function;<br />
    tvn_inner_function = &amp;GetR12();</p>
	<p>    *(int *)(tvn_inner_function.parentStack + offsetForX)++;<br />
}
</p>
]]></content:encoded>
				</item>
	<item>
		<title>by: Jens Ayton</title>
		<link>http://ridiculousfish.com/blog/archives/2006/02/05/nest/#comment-530</link>
		<pubDate>Mon, 06 Feb 2006 08:20:25 +0000</pubDate>
		<guid>http://ridiculousfish.com/blog/archives/2006/02/05/nest/#comment-530</guid>
					<description>Tweaks: that should be extern_function((void *)&amp;amp;tvn_inner_function) instead of extern_function(inner_function), and (NestTVector *)GetR12(), not &amp;amp;GetR12().</description>
		<content:encoded><![CDATA[	<p>Tweaks: that should be extern_function((void *)&amp;tvn_inner_function) instead of extern_function(inner_function), and (NestTVector *)GetR12(), not &amp;GetR12().
</p>
]]></content:encoded>
				</item>
</channel>
</rss>
