On Wed, 2014-01-29 at 21:38 +0000, Jonathan Wakely wrote: > On 29 January 2014 21:17, Oleg Endo wrote: > > My original intention was to eliminate code bloat when doing something > > like throw std::logic_error ("cold coffee"); > > If the const char* overloads are inlined it will emit code to construct > > an std::string from const char* in user code where the exception is > > being constructed over and over again. The idea was to move that code > > into the std library. > > That's exactly what happens today with the constructors that only take > a std::string, so it wouldn't be any worse than what we have now, > would it?
Sorry, I'm not sure I understand your question. Maybe you meant "any better than what we have"? Anyway, I've attached two outputs that show what I mean. The version with the const char* ctor overloads implemented in the library is significantly shorter in the throwing path (5x function call vs. 7x function call + other inlined std::string ctor code). > > > BTW the original patch was posted during Stage 3 (19.12.2013). I don't > > mind waiting until Stage 1 if adding exports now is a problem. > > OK, let's wait and decide how we want to do it properly in stage 1. Sure. Actually I've missed some of the other exception types in system_error, which should be added, too. That would eliminate the TODO: Add const char* ctors to all exceptions. I'd also propose moving the system_error ctor implementations into the library as well, for the same reasons as above. > > (If we're going to make various changes that impact the ABI during the > next stage 1 we might even want to consider changing the > std::exception base class to store something like a > std::shared_ptr<std::string> so that copying an exception object will > never throw an exception, which is something I've been thinking about > recently.) Wouldn't using std::shared_ptr<std::string> introduce an additional heap allocation when creating the exception, though? How about storing the exception message in a plain zero terminated string instead? This would require only one heap allocation if the string data is prefixed with a refcount variable. Basically, std::make_shared re-invented because it doesn't work with arrays. Or maybe implement N3640 + N3641 first (even if for library internal use only as a start)... Cheers, Oleg
.file "sh_tmp.cpp" .text .little .section .rodata.str1.4,"aMS",@progbits,1 .align 2 .LC0: .string "multiplication by zero" .text .align 1 .align 2 .global __Z6test03ii .type __Z6test03ii, @function __Z6test03ii: .LFB746: .cfi_startproc .cfi_personality 0,___gxx_personality_v0 .cfi_lsda 0xb,.LLSDA746 mov.l r8,@-r15 ! 183 movsi_ie/9 [length = 2] .cfi_def_cfa_offset 4 .cfi_offset 8, -4 mov.l r9,@-r15 ! 184 movsi_ie/9 [length = 2] .cfi_def_cfa_offset 8 .cfi_offset 9, -8 sts.l pr,@-r15 ! 185 movsi_ie/11 [length = 2] .cfi_def_cfa_offset 12 .cfi_offset 17, -12 add #-8,r15 ! 186 *addsi3_compact [length = 2] .cfi_def_cfa_offset 20 tst r5,r5 ! 7 cmpeqsi_t/1 [length = 2] bt/s .L19 ! 8 *cbranch_t [length = 2] mul.l r5,r4 ! 68 mul_l [length = 2] sts macl,r0 ! 116 movsi_ie/7 [length = 2] add #8,r15 ! 191 *addsi3_compact [length = 2] .cfi_remember_state .cfi_def_cfa_offset 12 lds.l @r15+,pr ! 193 movsi_ie/15 [length = 2] .cfi_restore 17 .cfi_def_cfa_offset 8 mov.l @r15+,r9 ! 194 movsi_ie/6 [length = 2] .cfi_restore 9 .cfi_def_cfa_offset 4 rts ! 197 *return_i [length = 2] mov.l @r15+,r8 ! 195 movsi_ie/6 [length = 2] .cfi_def_cfa_offset 0 .cfi_restore 8 .align 1 .L19: .cfi_restore_state mov.l .L21,r0 ! 171 movsi_ie/1 [length = 2] jsr @r0 ! 12 call_valuei [length = 2] mov #8,r4 ! 11 movsi_ie/3 [length = 2] mov.l .L22,r1 ! 170 movsi_ie/1 [length = 2] mov r15,r4 ! 174 movsi_ie/2 [length = 2] mov r15,r6 ! 175 movsi_ie/2 [length = 2] mov r0,r9 ! 13 movsi_ie/2 [length = 2] add #4,r4 ! 19 *addsi3_compact [length = 2] mov.l .L23,r5 ! 20 movsi_ie/1 [length = 2] .LEHB0: jsr @r1 ! 22 calli [length = 2] add #2,r6 ! 21 *addsi3_compact [length = 2] .LEHE0: mov.l .L24,r1 ! 169 movsi_ie/1 [length = 2] mov r15,r5 ! 176 movsi_ie/2 [length = 2] mov r9,r4 ! 26 movsi_ie/2 [length = 2] .LEHB1: jsr @r1 ! 28 calli [length = 2] add #4,r5 ! 27 *addsi3_compact [length = 2] .LEHE1: mov.l @(4,r15),r1 ! 32 movsi_ie/6 [length = 2] mov.l .L33,r2 ! 34 movsi_ie/1 [length = 2] mov r1,r4 ! 177 movsi_ie/2 [length = 2] add #-12,r4 ! 33 *addsi3_compact [length = 2] cmp/eq r2,r4 ! 35 cmpeqsi_t/3 [length = 2] bf/s .L20 ! 36 *cbranch_t [length = 2] add #-64,r1 ! 42 *addsi3_compact [length = 2] .L4: mov.l .L26,r1 ! 167 movsi_ie/1 [length = 2] mov.l .L27,r5 ! 62 movsi_ie/1 [length = 2] mov.l .L28,r6 ! 63 movsi_ie/1 [length = 2] .LEHB2: jsr @r1 ! 64 calli [length = 2] mov r9,r4 ! 61 movsi_ie/2 [length = 2] .align 1 .L11: mov r4,r8 ! 123 movsi_ie/2 [length = 2] .L17: mov.l .L34,r1 ! 147 movsi_ie/1 [length = 2] lds.l @r1+,fpscr ! 207 fpu_switch/2 [length = 2] .L10: mov.l .L30,r1 ! 165 movsi_ie/1 [length = 2] jsr @r1 ! 109 calli [length = 2] mov r9,r4 ! 108 movsi_ie/2 [length = 2] mov.l .L31,r1 ! 164 movsi_ie/1 [length = 2] jsr @r1 ! 113 calli [length = 2] mov r8,r4 ! 112 movsi_ie/2 [length = 2] .LEHE2: .align 1 .L20: mov.l @(60,r1),r2 ! 43 movsi_ie/6 [length = 2] mov r2,r3 ! 178 movsi_ie/2 [length = 2] add #-1,r3 ! 45 *addsi3_compact [length = 2] cmp/pl r2 ! 48 cmpgtsi_t/1 [length = 2] bt/s .L4 ! 49 *cbranch_t [length = 2] mov.l r3,@(60,r1) ! 46 movsi_ie/9 [length = 2] mov.l .L35,r1 ! 168 movsi_ie/1 [length = 2] mov r15,r5 ! 179 movsi_ie/2 [length = 2] jsr @r1 ! 55 calli [length = 2] add #3,r5 ! 54 *addsi3_compact [length = 2] bra .L4 nop ! 215 jump_compact [length = 4] .align 1 .L12: mov.l @(4,r15),r1 ! 77 movsi_ie/6 [length = 2] mov r4,r8 ! 129 movsi_ie/2 [length = 2] mov.l .L33,r2 ! 79 movsi_ie/1 [length = 2] mov r1,r4 ! 180 movsi_ie/2 [length = 2] add #-12,r4 ! 78 *addsi3_compact [length = 2] cmp/eq r2,r4 ! 80 cmpeqsi_t/3 [length = 2] bt .L17 ! 81 *cbranch_t [length = 2] add #-64,r1 ! 87 *addsi3_compact [length = 2] mov.l @(60,r1),r2 ! 88 movsi_ie/6 [length = 2] mov r2,r3 ! 181 movsi_ie/2 [length = 2] add #-1,r3 ! 90 *addsi3_compact [length = 2] cmp/pl r2 ! 93 cmpgtsi_t/1 [length = 2] bt/s .L17 ! 94 *cbranch_t [length = 2] mov.l r3,@(60,r1) ! 91 movsi_ie/9 [length = 2] mov.l .L34,r1 ! 153 movsi_ie/1 [length = 2] mov r15,r5 ! 182 movsi_ie/2 [length = 2] lds.l @r1+,fpscr ! 208 fpu_switch/2 [length = 2] mov.l .L35,r1 ! 166 movsi_ie/1 [length = 2] jsr @r1 ! 100 calli [length = 2] add #3,r5 ! 99 *addsi3_compact [length = 2] bra .L10 nop ! 217 jump_compact [length = 4] .L36: .align 2 .L21: .long ___cxa_allocate_exception .L22: .long __ZNSsC1EPKcRKSaIcE .L23: .long .LC0 .L24: .long __ZNSt11logic_errorC1ERKSs .L33: .long __ZNSs4_Rep20_S_empty_rep_storageE .L26: .long ___cxa_throw .L27: .long __ZTISt11logic_error .L28: .long __ZNSt11logic_errorD1Ev .L34: .long ___fpscr_values+4 .L30: .long ___cxa_free_exception .L31: .long __Unwind_Resume .L35: .long __ZNSs4_Rep10_M_destroyERKSaIcE .cfi_endproc .LFE746: .global ___gxx_personality_v0 .section .gcc_except_table,"a",@progbits .LLSDA746: .byte 0xff .byte 0xff .byte 0x1 .uleb128 .LLSDACSE746-.LLSDACSB746 .LLSDACSB746: .uleb128 .LEHB0-.LFB746 .uleb128 .LEHE0-.LEHB0 .uleb128 .L11-.LFB746 .uleb128 0 .uleb128 .LEHB1-.LFB746 .uleb128 .LEHE1-.LEHB1 .uleb128 .L12-.LFB746 .uleb128 0 .uleb128 .LEHB2-.LFB746 .uleb128 .LEHE2-.LEHB2 .uleb128 0 .uleb128 0 .LLSDACSE746: .text .size __Z6test03ii, .-__Z6test03ii
.file "sh_tmp.cpp" .text .little .section .rodata.str1.4,"aMS",@progbits,1 .align 2 .LC0: .string "multiplication by zero" .text .align 1 .align 2 .global __Z6test03ii .type __Z6test03ii, @function __Z6test03ii: .LFB746: .cfi_startproc .cfi_personality 0,___gxx_personality_v0 .cfi_lsda 0xb,.LLSDA746 tst r5,r5 ! 7 cmpeqsi_t/1 [length = 2] bt/s .L9 ! 8 *cbranch_t [length = 2] mul.l r5,r4 ! 31 mul_l [length = 2] rts ! 81 *simple_return_i [length = 2] sts macl,r0 ! 47 movsi_ie/7 [length = 2] .align 1 .L9: mov.l r8,@-r15 ! 73 movsi_ie/9 [length = 2] .cfi_def_cfa_offset 4 .cfi_offset 8, -4 mov.l r9,@-r15 ! 74 movsi_ie/9 [length = 2] .cfi_def_cfa_offset 8 .cfi_offset 9, -8 sts.l pr,@-r15 ! 75 movsi_ie/11 [length = 2] .cfi_def_cfa_offset 12 .cfi_offset 17, -12 mov.l .L10,r0 ! 71 movsi_ie/1 [length = 2] jsr @r0 ! 12 call_valuei [length = 2] mov #8,r4 ! 11 movsi_ie/3 [length = 2] mov.l .L11,r1 ! 70 movsi_ie/1 [length = 2] mov r0,r8 ! 13 movsi_ie/2 [length = 2] mov.l .L12,r5 ! 18 movsi_ie/1 [length = 2] .LEHB0: jsr @r1 ! 19 calli [length = 2] mov r0,r4 ! 17 movsi_ie/2 [length = 2] .LEHE0: mov.l .L13,r1 ! 69 movsi_ie/1 [length = 2] mov.l .L14,r5 ! 25 movsi_ie/1 [length = 2] mov.l .L15,r6 ! 26 movsi_ie/1 [length = 2] .LEHB1: jsr @r1 ! 27 calli [length = 2] mov r8,r4 ! 24 movsi_ie/2 [length = 2] .align 1 .L4: mov.l .L16,r1 ! 64 movsi_ie/1 [length = 2] mov r4,r9 ! 54 movsi_ie/2 [length = 2] lds.l @r1+,fpscr ! 82 fpu_switch/2 [length = 2] mov.l .L17,r1 ! 68 movsi_ie/1 [length = 2] jsr @r1 ! 40 calli [length = 2] mov r8,r4 ! 39 movsi_ie/2 [length = 2] mov.l .L18,r1 ! 67 movsi_ie/1 [length = 2] jsr @r1 ! 44 calli [length = 2] mov r9,r4 ! 43 movsi_ie/2 [length = 2] .LEHE1: .L19: .align 2 .L10: .long ___cxa_allocate_exception .L11: .long __ZNSt11logic_errorC1EPKc .L12: .long .LC0 .L13: .long ___cxa_throw .L14: .long __ZTISt11logic_error .L15: .long __ZNSt11logic_errorD1Ev .L16: .long ___fpscr_values+4 .L17: .long ___cxa_free_exception .L18: .long __Unwind_Resume .cfi_endproc .LFE746: .global ___gxx_personality_v0 .section .gcc_except_table,"a",@progbits .LLSDA746: .byte 0xff .byte 0xff .byte 0x1 .uleb128 .LLSDACSE746-.LLSDACSB746 .LLSDACSB746: .uleb128 .LEHB0-.LFB746 .uleb128 .LEHE0-.LEHB0 .uleb128 .L4-.LFB746 .uleb128 0 .uleb128 .LEHB1-.LFB746 .uleb128 .LEHE1-.LEHB1 .uleb128 0 .uleb128 0 .LLSDACSE746: .text .size __Z6test03ii, .-__Z6test03ii