Troubles with immutable arrays
bearophile
bearophileHUGS at lycos.com
Mon Jul 23 06:29:18 PDT 2012
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
More information about the Digitalmars-d
mailing list