Does foreach on array literal allocate?

Walter Bright newshound1 at digitalmars.com
Thu Dec 4 17:37:05 PST 2008


Bill Baxter wrote:
> Does anyone know off the top of their head if code like this allocates
> or not with current DMD 1.x compilers?
> 
> foreach(x; [1, 2, 3, 4])
> {
>      // do something non-allocating with x
> }

Here's how to find out. Compile:

void test()
{
     foreach(x; [1, 2, 3, 4])
     {
          // do something non-allocating with x
     }
}

Obj2asm the output:

_D5test44testFZv        comdat
         assume  CS:_D5test44testFZv
L0:             enter   8,0
                 push    EBX
                 push    4
                 push    3
                 push    2
                 push    1
                 push    4
                 push    offset FLAT:_D12TypeInfo_G4i6__initZ
                 call    near ptr __d_arrayliteralT
                 mov     -8[EBP],EAX
                 lea     EAX,010h[EAX]
                 mov     -4[EBP],EAX
                 add     ESP,018h
L25:            mov     ECX,-8[EBP]
                 cmp     ECX,-4[EBP]
                 jae     L38
                 mov     EDX,-8[EBP]
                 mov     EBX,[EDX]
                 add     dword ptr -8[EBP],4
                 jmp short       L25
L38:            pop     EBX
                 leave
                 ret
_D5test44testFZv        ends

Look up _d_arrayliteralT in the runtime library:

extern (C) void* _d_arrayliteralT(TypeInfo ti, size_t length, ...)
{
     auto sizeelem = ti.next.tsize();            // array element size
     void* result;

     debug(PRINTF) printf("_d_arrayliteralT(sizeelem = %d, length = 
%d)\n", sizeelem, length);
     if (length == 0 || sizeelem == 0)
         result = null;
     else
     {
         result = gc_malloc(length * sizeelem, !(ti.next.flags() & 1) ? 
BlkAttr.NO_SCAN : 0);

         va_list q;
         va_start!(size_t)(q, length);

         size_t stacksize = (sizeelem + int.sizeof - 1) & ~(int.sizeof - 1);

         if (stacksize == sizeelem)
         {
             memcpy(result, q, length * sizeelem);
         }
         else
         {
             for (size_t i = 0; i < length; i++)
             {
                 memcpy(result + i * sizeelem, q, sizeelem);
                 q += stacksize;
             }
         }

         va_end(q);
     }
     return result;
}

and note the call to gc_malloc().



More information about the Digitalmars-d mailing list