[M3devel] function pointers and comparison to nil? mis-typed function pointers?
jayk123 at hotmail.com
Sun Jun 1 03:40:42 CEST 2008
> In Modula-3, you can pass any procedure but only assign a top-level procedure. > This precludes dangling environments in yet another way, that is more liberal > than either Pascal or Modula-2,, but requires a runtime check on procedure
I don't understand "can only assign a top-level procedure".
My understanding is that Modula-3 does allow the "unsafe" option -- take the address of a nested function, pass it off to some code, that stores it in a global, and call it later. But of course, "Modula-3 does allow the unsafe option" does not compute. I need to read up and experiment.
Maybe there is a runtime check whenever I assign a function pointer to either a global or to a field in non-local record, that it isn't a closure?
That makes a fair amount of sense though hard to not make the check overly strict I think.
Rodney my "problem" with your analysis is it mostly "pretends" that each language is its own independent environment.
In present reality at least, Modula-3 and C interoperate a lot. That is largely a good thing. It does place restrictions on Modula-3 implementations however.
Pointers to top-level Modula-3 functions can be passed to C and treated as pointers to C functions.
Pointers to C functions, including gcc nested functions, can be passed to Modula-3 code as pointers.
There are not separate types for pointers to C vs. Modula-3 functions.
Pointers to nested Modula-3 functions cannot be passed to C code and treated as C function pointers, though enabling this, with the programmer required to notice the situation and change the code slightly, is easy enough. The compiler might also be able to recognize it and possibly error, at least if "extern" is presumed to be C, though of course..insert one level of Modula-3 code between "taking the address" and "passing it to C", and it becomes more difficult..but maybe still quite easy.
If the whole world was Modula-3, then you could just change the representation of all function pointers and how they are called.
The strategy of optionally heap allocated frames -- when the address is taken of a nested function -- does kill multiple birds with one expensive stone.
- ability to pass function pointers to nested functions to C code, and store them anywhere
- ability to call nested functions after their caller has returned
- remove the check for the -1 marker which might possibly maybe just barely be unportable, and also slows down/bloats calls to function pointers (but at the cost of probably a more sever slow down)
- avoid the use of generated code on the stack
- still need to ensure the heap is executable but that's less of a problem, Windows for example at least exposes the ability to make the heap executable, besides the strategy of using VirtualAlloc.
However it slows down existing code.
Depending on which of these features is desirable, if in fact any at all, there are other options.
- leave it all alone (but continue talking about it :) )
- put the code on the stack and call mprotect/VirtualProtect, as OpenBSD does for gcc nested functions
> Date: Sat, 31 May 2008 09:29:24 -0400> From: hendrik at topoi.pooq.com> To: m3devel at elegosoft.com> Subject: Re: [M3devel] function pointers and comparison to nil? mis-typed function pointers?> > On Fri, May 30, 2008 at 06:17:02PM -0500, Rodney M. Bates wrote:> > > > My one handy Algol68 book has the usual tutorial language book problem: it> > omits the cases you really need to look up. It only states that there will> > be problems if you use a dangling environment, but not whether the language> > specifies this should be detected by the language, or whether "all hell will> > break loose." I'm guessing it's the latter. The implementation technique> > Hendrik describes makes it a detected runtime error, but not unless/until> > you try to use the lost environment. This is more generous than Modula-3's > > rule.> > The actual Algol 68 definition does pronounce on this. The CDC > implementation was much more liberal than the language definition.> > Every reference/variable and every procedure has a scope. The scope of > a variable is the level on the run-time stack at which it is allocated. > Variables can be on the heap; this is global scope. The scope of a > procedure is the stack elvel at which its most local global identifier > is bound. Even if the identifier refers to an object on the heap, it is > the level at which it is bound that counts.> > There is a universal scope restriction: No object can refer to a more > local object. The constraint in the language definition is applied on > assignment.> > I know of no Algol 68 implementation that I can say for sure implements > this restriction with a run-time check. Of course it can be done, > either by tagging each pointer with an explicit mention of its stack > level (which takes space) or by comparing its value and comparing it to > various stack locations in a kind of search.> > The first release of the CDC algol 68 compiler just allocated all > variables on the heap, making the check unnecessary for safety. > Programmers almost never wrote code that passed procedures out-of-scope.> > Later releases performed static analysis to determine where it was safe > to allocate in the stack (almost all the time), and used the mechanism I > described earlier to check procedures when they were called if the > static check didn't suffice..> > > > And, of course, if your language is really dynamic, it could just say an> > environment is always accessible, requiring many or all activation records> > to be heap allocated.> > Which was a proposal made for the original Algol 68, but was turned > down. I think it should have been accepted. We would have had a > strongly-typed Scheme ahead of its time.> > -- hendrik>
-------------- next part --------------
An HTML attachment was scrubbed...
More information about the M3devel