On Mon, 2012-03-05 at 15:29 +0000, Michael Meeks wrote: > On Fri, 2012-03-02 at 17:16 +0000, Caolán McNamara wrote: > At the most banal level, I suspect that: > > struct Empty { int unused; }; > Empty *p = new Empty(); > delete p; > > can't legitimately be optimised away if we have a throwing constructor, > but of course I can dig out some compiler people who know what they're > on about here.
In the general case presumably you then need to run around sticking throw()/nothrow onto loads of things in order to tell the compiler that stuff isn't going to throw exceptions, and/or disabling exceptions to get the compiler to do something different. Amusingly, for the trivial example #include <new> void foo() { struct Empty { int unused; }; #ifdef TESTNOTHROW Empty *p = new(std::nothrow) Empty(); #else Empty *p = new Empty(); #endif delete p; } and pure .o size. g++ -O2 -DTESTNOTHROW -c test.cxx gives a 1060byte .o while g++ -O2 -c test.cxx gives a 996 byte .o and g++ -O2 -fno-exceptions -c test.cxx gives a 996 byte .o as well. Doesn't appear to be the case that gcc optimizes out the call to new regardless of what optimization level or -fno-exceptions that might let it know it could do it if it wanted. > Consistently calling std::abort() somewhere rather than waiting for a > SEGV sounds fine, though preferably not in-lined into many tens if not > hundreds of thousands of duplicate compare/branch/call-function sides at > every object construction. Looking at std::abort vs std::throw for new, assuming something is built with -fexceptions, and once there's *something* in a function called that might throw an exception I *guess* you pay a fixed penalty and it doesn't really matter how many things in that function might throw something ?, that's the way I internalized it anyway. Anyway, FWIW I'm not massively interested in the allocate, "oh we don't have enough, lets try and release some" unrealistic path, just the load binary file format scenario of int32_t foo = read_foo(); new Foo[foo] where foo is approx MAX_SIZE, and new should immediately throws without even making any effort to allocate, given that the number to allocate would overflow and the .wmf/.doc or whatever import is aborted with a toplevel import-level catch without the app exiting. If we didn't have a single-process-app none of this would matter much I suppose. > I guess I now need to go and characterise how much of the saving is > from removing tens of thousands of in-lined 'if (baa) throw > std::bad_alloc();' calls vs. the exception unwind and knock-on optimiser > impact of having all that there. hmm, initially I would have said that the savings must all be from the removal of the inlining of the "check for NULL and throw itself" given that the compiler can only see the body of rtl_uString2String when building one object file and not for any of the others, but I see now that rtl_uString2String is marked as nothrow so the compiler could make use of that I guess. C. _______________________________________________ LibreOffice mailing list LibreOffice@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice