Why does scope(success) have to use exceptions?
Andrej Mitrovic
andrej.mitrovich at gmail.com
Wed Jan 16 15:19:09 PST 2013
Sample code:
void callScope(ref int x)
{
x = 1;
scope(success) { x = 2; }
x = 3;
scope(success) { x = 4; }
}
void callFunc(ref int x)
{
x = 1;
x = 3;
x = 4;
x = 2;
}
void main()
{
int x;
callScope(x);
assert(x == 2);
callFunc(x);
assert(x == 2);
}
I was expecting callScope to be lowered down to the handwritten code
in callFunc in assembly, but instead it uses exceptions. Here's some
simple ASM for callFunc compiled with -c -release -O (no inline):
_D4test8callFuncFKiZv:; Function begin, communal
mov dword [eax], 1 ; 0000 _ C7.
00, 00000001
mov ecx, eax ; 0006 _ 89. C1
mov dword [ecx], 3 ; 0008 _ C7.
01, 00000003
mov dword [ecx], 4 ; 000E _ C7.
01, 00000004
mov dword [ecx], 2 ; 0014 _ C7.
01, 00000002
ret ; 001A _ C3
; _D4test8callFuncFKiZv End of function
And this monster code for callScope:
_D4test9callScopeFKiZv:; Function begin, communal
push ebp ; 0000 _ 55
mov ebp, esp ; 0001 _ 8B. EC
mov edx, dword [fs:__except_list] ; 0003 _ 64:
8B. 15, 00000000(segrel)
push -1 ; 000A _ 6A, FF
mov ecx, 1 ; 000C _ B9, 00000001
push _D4test9callScopeFKiZv+0A6H ; 0011 _ 68,
000000A6(segrel)
push edx ; 0016 _ 52
mov dword [fs:__except_list], esp ; 0017 _ 64:
89. 25, 00000000(segrel)
sub esp, 24 ; 001E _ 83. EC, 18
push ebx ; 0021 _ 53
push esi ; 0022 _ 56
push edi ; 0023 _ 57
mov dword [ebp-18H], eax ; 0024 _ 89. 45, E8
mov dword [eax], ecx ; 0027 _ 89. 08
mov byte [ebp-1CH], 0 ; 0029 _ C6. 45, E4, 00
mov dword [ebp-4H], 0 ; 002D _ C7.
45, FC, 00000000
mov dword [ebp-4H], ecx ; 0034 _ 89. 4D, FC
mov dword [eax], 3 ; 0037 _ C7.
00, 00000003
xor ecx, ecx ; 003D _ 31. C9
mov dword [eax], 4 ; 003F _ C7.
00, 00000004
mov dword [ebp-4H], ecx ; 0045 _ 89. 4D, FC
jmp ?_002 ; 0048 _ EB, 0C
; Note: Inaccessible code
mov byte [ebp-1CH], 1 ; 004A _ C6. 45, E4, 01
push dword [ebp-20H] ; 004E _ FF. 75, E0
call __d_throwc ; 0051 _ E8,
00000000(rel)
?_002: mov dword [ebp-4H], -1 ; 0056 _ C7.
45, FC, FFFFFFFF
; Note: Displacement could be made smaller by sign extension
lea ecx, [ebp-0CH] ; 005D _ 8D.
8D, FFFFFFF4
push -1 ; 0063 _ 6A, FF
push ecx ; 0065 _ 51
push FLAT:?_001 ; 0066 _ 68,
00000000(segrel)
call __d_local_unwind2 ; 006B _ E8,
00000000(rel)
add esp, 12 ; 0070 _ 83. C4, 0C
call ?_003 ; 0073 _ E8, 00000002
jmp ?_005 ; 0078 _ EB, 18
?_003: mov dword [ebp-4H], -1 ; 007A _ C7.
45, FC, FFFFFFFF
mov al, byte [ebp-1CH] ; 0081 _ 8A. 45, E4
xor al, 01H ; 0084 _ 34, 01
jz ?_004 ; 0086 _ 74, 09
mov edx, dword [ebp-18H] ; 0088 _ 8B. 55, E8
mov dword [edx], 2 ; 008B _ C7.
02, 00000002
?_004: ret ; 0091 _ C3
?_005:
; Note: Displacement could be made smaller by sign extension
mov ecx, dword [ebp-0CH] ; 0092 _ 8B.
8D, FFFFFFF4
mov dword [fs:__except_list], ecx ; 0098 _ 64:
89. 0D, 00000000(segrel)
pop edi ; 009F _ 5F
pop esi ; 00A0 _ 5E
pop ebx ; 00A1 _ 5B
mov esp, ebp ; 00A2 _ 8B. E5
pop ebp ; 00A4 _ 5D
ret ; 00A5 _ C3
; _D4test9callScopeFKiZv End of function
I'm trying to understand why. If an exception is thrown between one of
those assignment statements the stack will unwind and any following
assignment statements will not be called, so there shouldn't be a need
to check if an exception is thrown. Why doesn't the compiler simply
rewrite callScope to look like callFunc?
More information about the Digitalmars-d
mailing list