From: | "cr88192" <cr88192@hotmail.com> |
Newsgroups: | comp.compilers |
Date: | Fri, 27 Feb 2009 21:16:46 +1000 |
Organization: | albasani.net |
References: | 09-02-021 09-02-037 09-02-076 09-02-082 09-02-089 09-02-095 09-02-103 09-02-109 09-02-114 09-02-122 09-02-124 09-02-133 |
Keywords: | debug, code |
Posted-Date: | 27 Feb 2009 07:39:02 EST |
"George Neuner" <gneuner2@comcast.net> wrote in message
> On Wed, 25 Feb 2009 17:08:41 +1000, "cr88192" <cr88192@hotmail.com>
> wrote:
>
>>well, there are many uses [of frame pointers] beyond debugging...
>>
>>other uses include:
>>stack unwinding in some approaches to exception handling (IP-range based
>>exception handlers);
>
> I'm not sure what specific deficiency you think IP-range exception
> handling has that it requires use of frame pointers.
the frame pointers typically give both the prior frame pointer, and also the
return IP.
absent this, it is only possible to unwind if you know the layout of the
current frame, the parent frame, ...
but, just as soon as an unknown IP is found (say, code produced by an
unknown compiler), then it is no longer possible to find the next IP and the
super-frame.
as a result, one needs to have accurate and complete information available
to unwind without the frame pointer...
>>simplifying reflection ability and allowing precise garbage collection;
>>...
>
> I won't go into what I think about performing reflection on stalled
> functions except to say I think debugging is the only valid reason to
> do it.
I guess it depends on the language.
for example, what if the source language being compiled is JavaScript or
Scheme and this info is actually needed for something?...
> As for GC, there are ways to implement precise GC of the stack that
> don't need a frame pointer. The most obvious is tagged data, but that
> isn't necessary either. Another possibility is to make it IP-based
> (like exceptions). Since the compiler knows the frame layout, it can
> associate with each user function a small GC function that processes
> the frame, identifies the caller from the return address and
> progressively calls the callers GC function, etc.
>
the problem though is that the compiler may not know the frame layout...
for example, consider one calls into MSVC produced code (such as the Win32
API), which calls back into the app via a callback. then, we have a mess...
> [I'm actually a fan of making GC based on special purpose functions as
> much as possible rather than embedding pointer maps everywhere and
> having generic code interpret them. IME using special functions
> simplifies the GC and it's interface to the runtime (GC only needs to
> know how to call a function given a data object) and results in better
> data locality and cache behavior.]
>
possibly, but I tend to use a "generic plug-in" approach, where some code,
such as part of the runtime, registers callbacks with the garbage collector
to allow it to GC certain kinds of things.
now, the runtime would then probably use generic code to unwind the stack
for each thread (but, then again, there is the issue that this could still
be problematic if the thread is still running at the time...).
>
>>for example, due to this deficiency one has to use another location to
>>hold
>>a list of linked exception frames, which actually hurts raw performance in
>>general (universally keeping the frame pointer allows very lightweight
>>exception handling, since the only time anything is actually done
>>specially
>>is during the exception itself, but otherwise the code is structured as if
>>there were no exception handler).
>>
>>now, with no frame pointer, the compiler has to go and endlessly link in
>>and
>>unlink exception frames (representing the try block), which is not free...
>>and the compiler can't just simply add this cheaper approach, because it
>>is
>>not possible to implicitly unwind.
>
> This all depends on the implementation. I can easily envision using
> dual stacks: a control stack with fixed sized structures and a
> separate data stack framed implicitly. I can think of a few other
> unconventional implementations as well.
>
yes, but this breaks direct call-compatibility with existing code...
> I understand that one of the goals of your project is to mix in
> existing code, but that particular focus is coloring your thoughts.
> Features like frame pointers evolve because they are either necessary
> or helpful in a particular context. Change the context and they can
> become irrelevant.
>
maybe, but in this case (typical x86 and x86-64 calling conventions), they
are needed...
now, Win64 uses a magic epilogue approach, which is interesting (we don't
need a frame pointer, since the assembly code for the epilogue implicitly
tells the compiler how to unwind, and also the code is structured in such a
way that it can be "recognized" via a linear scan).
but, alas, neither cdecl nor stdcall do this, so no luck there...
>
>>the issue is not so much debugging, but the frame-pointer may be useful in
>>in implementing many kinds of compiler and runtime features, which are
>>then
>>fouled up by the presence of code in the call frame which does not allow
>>proper unwinding, and where the information necessary for this unwinding
>>is
>>not available.
>
> I'm not disagreeing with you ... frame pointers are useful for lots of
> things. I'm just playing devil's advocate to get you thinking about
> it.
ok.
>>the lack of information leads to many kinds of difficulties, which is
>>partly
>>why traditionally C and C++ are forced to use conservative garbage
>>collectors, ... when, technically, it would not cost much for the compiler
>>to leave the necessary information in the app itself (be it something as
>>simple as a frame pointer, to the symbol table, to the type annotations of
>>variables and functions, ...).
>
> Sorry, this is a fallacy. Completely precise GC is not possible in C
> or C++ ... the language semantics don't allow it. The best that can
> be achieved without revising the language specs is to be conservative
> in the stack and to be as precise as possible in the global roots and
> heap. It is possible to be precise in the heap unless there are
> untagged unions ... if so, you are back to guessing.
yeah, I guess if one is allocating memory with a malloc-style interface then
there is inherently a problem (I typically type-tag allocations, ...).
but, I had assumed that the code in question would be being cooperative,
rather than expecting precise GC to work in all cases...
as is, it would be necessary to register and unregister root-frames to do
precise GC, which is expensive...
(all of these issues have been enough at times to challenge my commitment to
cdecl...).
> Bartlett, Boehm, Detlef, Ellis and others have written at length about
> the problems of adding GC to uncooperative languages. Boehm, in
> particular, has written a lot about how to improve conservative
> pointer guessing by eliminating impossible values. Detlef and Ellis
> have a current proposal for a library based GC to be added to C++.
> Google is your friend.
>
I know about a lot of this...
Return to the
comp.compilers page.
Search the
comp.compilers archives again.