After a discussion in D.learn started by someone else, after a suggestion of mine Timon Gehr has added a bug report:

http://d.puremagic.com/issues/show_bug.cgi?id=8400

But the bug was fixed in the opposite way of what I was thinking.

The problem was that the length of global immutable arrays arrays is seen as a compile-time constant. Instead of fixing that, Issue 8400 has done the opposite, now even the lenght of local immutable arrays is seen sometimes as a compile-time constant, and example:


int[] foo(in int n) pure nothrow {
    int[] a;
    foreach (i; 0 .. n)
        a ~= i * 10;
    return a;
}
void main() {
    import core.stdc.stdio: printf;
    immutable int[] A = foo(5);
    int[A.length] B;
    printf("%zd\n", B.length);
}



The asm, compiled with -release:

_D4temp3fooFNaNbxiZAi   comdat
L0:     enter   018h,0
        push    EBX
        push    ESI
        mov dword ptr -018h[EBP],0
        mov dword ptr -014h[EBP],0
        mov dword ptr -010h[EBP],0
        mov -0Ch[EBP],EAX
L1E:        mov EAX,-010h[EBP]
        cmp EAX,-0Ch[EBP]
        jge L48
        lea ECX,-010h[EBP]
        mov EDX,[ECX]
        lea EBX,[EDX*4][EDX]
        add EBX,EBX
        push    EBX
        lea ESI,-018h[EBP]
        push    ESI
        mov EAX,offset FLAT:_D11TypeInfo_Ai6__initZ
        push    EAX
        call    near ptr __d_arrayappendcT
        add ESP,0Ch
        inc dword ptr -010h[EBP]
        jmp short   L1E
L48:        mov EDX,-014h[EBP]
        mov EAX,-018h[EBP]
        pop ESI
        pop EBX
        leave
        ret

__Dmain comdat
L0:     enter   018h,0
        push    EBX
        push    ESI
        push    5
        mov EAX,offset FLAT:_D11TypeInfo_Ai6__initZ
        push    EAX
        call    near ptr __d_arrayliteralTX
        mov dword ptr [EAX],0
        mov dword ptr 4[EAX],0Ah
        mov dword ptr 8[EAX],014h
        mov dword ptr 0Ch[EAX],01Eh
        mov dword ptr 010h[EAX],028h
        mov ECX,EAX
        mov EBX,5
        lea EDX,-018h[EBP]
        xor EAX,EAX
        mov [EDX],EAX
        mov 4[EDX],EAX
        mov 8[EDX],EAX
        mov 0Ch[EDX],EAX
        mov 010h[EDX],EAX
        push    5
        mov ESI,offset FLAT:_DATA
        push    ESI
        call    near ptr _printf
        xor EAX,EAX
        add ESP,010h
        pop ESI
        pop EBX
        leave
        ret



This code too compiles, so A is sometimes computed at run-time and sometimes at compile-time:

int[] foo(in int n) pure nothrow {
    int[] a;
    foreach (i; 0 .. n)
        a ~= i * 10;
    return a;
}
void main() {
    import core.stdc.stdio: printf;
    int n = 5;
    immutable int[] A = foo(n);
}



Now immutable arrays are sometimes seen as enums. I think this is a problem. I think in D compile-time is run only if it's evaluated in a context where compile-time values are required. But now the situation is more muddy, because knowing n at compile-time is not a way to ask A to be computed at compile-time.

Another problem is that compile-time arrays in many situations are not efficient, they gets copied every time you use them, and I think that __d_arrayliteralTX performs a heap allocation. So now both enum and immutable arrays perform heap allocations every time you use them, but only in some situations.

I think this is a messy situation, I think the fix for bug 8400 should be undone, and I think Issue 8400 should be fixed the other way, turning global immutable arrays too into run-time entities.

The bug was fixed by Hara and accepted by Walter, both of them are very intelligent, so maybe I am just very wrong :-)

Bye,
bearophile

Reply via email to