3 ms·
Large, portable, robust programs are hard to write. But that's not what I'm addressing. I'm trying to show how what is generally considered a complex problem is
by radicandor 12y ago
Large, portable, robust programs are hard to write. But that's not what I'm addressing. I'm trying to show how what is generally considered a complex problem is simple when you strip it down to its essence.
- kazinator 12y ago"Local variables can also be stored in registers, but we won't worry about this because registers and usually dedicated to local variables, and by the time our function is called they'll probably be saved on the stack anyway" This is wrong; you have to take care of registers. The good noews is that an easy way to do this that will work on a broad range of platforms is to store the machine context to a jmp_buf that is on the stack. (You never use this jmp_buf for a longjmp, obviously.)
- MaulingMonkey 12y agoRelying on "probably" is completely the wrong foot to start out on, IMO. It leads to this kind of craziness: http://timetobleed.com/the-broken-promises-of-mrireeyarv/ http://timetobleed.com/the-broken-promises-of-mrireeyarv/
- kazinator 12y agoI think the article does not really articulate the root cause properly. The issue is that a Ruby object goes out of scope, while a low-level pointer to its internals continues to be used (in the middle of code that allocates and can trigger GC). How that problem translates to code generation on amd64 is secondary. What is happening is that the string object has been reduced to its C fundamentals (pointer to data, and length), and the one and only variable ("str") which holds the original object from which these fundamentals are derived has no next use after that. The fix in the patch is not very good; the real fix is to get rid of the nasty macro zstream_append_input2, and make it a real function. The function still has to solve the problem of pinning the object while the low level pointer is used, but it's more localized: we don't have to think about the interaction of the macro with the site where it is expanded (and will the hack always work). In other words, don't write macros that break apart garbage-collected objects into low-level C pointers to their internals that are invisible to the collector. The macros spread dangerous code everywhere they are used.
- MaulingMonkey 12y ago> The issue is that a Ruby object goes out of scope, while a low-level pointer to its internals continues to be used (in the middle of code that allocates and can trigger GC). How that problem translates to code generation on amd64 is secondary. "Out of scope" as defined how? Not by the C code, it can be in-scope in C but optimized away by the compiler... which seems best illustrated by dissecting the compiler's output. > The fix in the patch is not very good; the real fix is to get rid of the nasty macro zstream_append_input2, and make it a real function. That "real fix" doesn't actually fix anything, though. Don't get me wrong, macros are ugly (especially lowercase ones) and that's a fine refactoring to suggest, but it's not a fix. > In other words, don't write macros that break apart garbage-collected objects into low-level C pointers to their internals that are invisible to the collector. The macros spread dangerous code everywhere they are used. In this context, there's extremely little difference between a macro and a function that the compiler decides to inline.