From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 22918 invoked by alias); 7 May 2003 21:21:04 -0000 Mailing-List: contact gcc-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Archive: List-Post: List-Help: Sender: gcc-owner@gcc.gnu.org Received: (qmail 22881 invoked from network); 7 May 2003 21:21:01 -0000 Received: from unknown (HELO lacrosse.corp.redhat.com) (66.187.233.200) by sources.redhat.com with SMTP; 7 May 2003 21:21:01 -0000 Received: from prospero.boston.redhat.com (sebastian-int.corp.redhat.com [172.16.52.221]) by lacrosse.corp.redhat.com (8.11.6/8.9.3) with ESMTP id h47LKxi06074; Wed, 7 May 2003 17:20:59 -0400 Received: by prospero.boston.redhat.com (Postfix, from userid 4046) id 27832F8EB7; Wed, 7 May 2003 17:20:59 -0400 (EDT) To: Mark Mitchell Cc: gcc@gcc.gnu.org, Jason Merrill Subject: Re: __attribute__((cleanup(function)) versus try/finally From: Jason Merrill In-Reply-To: <1052256289.2583.412.camel@doubledemon.codesourcery.com> (Mark Mitchell's message of "06 May 2003 14:24:49 -0700") References: <1052245742.2583.315.camel@doubledemon.codesourcery.com> <1052249890.31850.338.camel@doubledemon.codesourcery.com> <1052256289.2583.412.camel@doubledemon.codesourcery.com> Date: Wed, 07 May 2003 21:21:00 -0000 Message-ID: User-Agent: Gnus/5.090019 (Oort Gnus v0.19) Emacs/21.2 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-SW-Source: 2003-05/txt/msg00705.txt.bz2 On 06 May 2003 14:24:49 -0700, Mark Mitchell wrote: >> cancellation exception specially. When you run out of unwind info, rather >> than call terminate you need to hand off to the old pthread_exit. > > I had suggested simply having the pthread-launching routine (the first > thing called in the new thread) be written in C++. It can then just > catch the exception and do whatever's required. Sure, that works so long as you don't run out of unwind info. >> >> > The try/finally solution cannot be implemented with this same >> >> > performance; it will, in fact, exact a performance price, in terms of >> >> > both code space and the speed at which cleanups are run, on all >> >> > systems. On systems with setjmp/longjmp exceptions, both costs will be >> >> > very high indeed. >> >> I think you're exaggerating the costs. This is the way the C++ frontend >> works, and you only incur the costs when you use the feature. The design >> philosophy of EH has always been that the speed of the normal code is what >> matters, not the cleanups. > > With setjmp/longjmp, there are big costs even if you don't use the > feature. There are no costs unless there are cleanups. > With the scheme I propose, you shouldn't need as many setjmps -- you only > need one setjmp at the beginning of the function to be able to unwind. > You never need to land in the middle of the function. The C++ setjmp/longjump EH scheme also only requires one setjmp per function unless there are nested catches; the EH runtime jumps there, runs all the cleanups for the current function, and calls back into the unwinder. > Without setjmp/longjmp, you save mostly code space. You also improve > cleanup time (in that you need not transfer control to the local frame > of the function before running the cleanup), but this is a smaller > advantage. Which may or may not outweigh the advantages of having the cleanups in the function (code motion into the landing pad, inlining destructors, not forcing the argument into the stack). How to run simple cleanups (a call to a function which takes a pointer to an object in the current frame) is an optimization question. We already have to handle more complex cleanups for Java try/finally, and for inlined destructors in C++. Allowing people to write them in C doesn't make our job any harder. >> > The observation behind this is that pthread cleanups -- unlike C++ catch >> > clauses -- do not need to execute in the frame of the function that >> > pushed them. They just need to execute while the stack is still there, >> > in case the "arg" to the function directly or indirectly references >> > stuff on the stack. >> >> No, they don't need to. Nor do C++ destructors. But they do anyway. > > Catch-clauses and destructors are different. I don't disagree. > Given: > > int i; > try { ... } catch (...) { i = 3; } > > the catch-clause had better execute in the frame of this function. > > With a destructor or (analogously) a pthread cleanup handler, the > execution just has to take place while the frame is still active. Well, if you really wanted to, you could turn the catch clause into a nested function which takes an argument pointing to the frame, though you probably wouldn't want to, as it would force all variables used in the catch clause into the stack. My point, however, was that in the current implementation, destructors are run within the frame of the function, even though they don't need to be. We could make a different choice, but again, it's just a question of optimization strategy. The same choices would apply to Java and C. Basically, what I'm saying is that the question of what sorts of cleanups to allow can be separated from the question of how to implement them. If we can set aside the implementation issues, it becomes just a question of language design, and I still think that try/finally is the elegant solution. Jason