Jump to page: 1 2
Thread overview
Do array literals still always allocate?
May 13, 2017
Lewis
May 13, 2017
Stanislav Blinov
May 14, 2017
Lewis
May 14, 2017
Namespace
May 14, 2017
Nicholas Wilson
May 13, 2017
Nicholas Wilson
May 14, 2017
ag0aep6g
May 14, 2017
Nicholas Wilson
May 14, 2017
ag0aep6g
May 14, 2017
Eugene Wissner
May 14, 2017
ag0aep6g
May 14, 2017
Nicholas Wilson
May 13, 2017
import std.random;
import std.stdio;

int[4] testfunc(int num) @nogc
{
    return [0, 1, num, 3];
}

int main()
{
    int[4] arr = testfunc(uniform(0, 15));
    writeln(arr);
    return 0;
}

I've read a bunch of stuff that seems to indicate that array literals are always heap-allocated, even when being used to populate a static array. However, testfunc() above compiles as @nogc. This would indicate to me that D does the smart thing and avoids a heap allocation for an array literal being used to populate a static array. Is all the old stuff I was reading just out-of-date now?
May 13, 2017
On Saturday, 13 May 2017 at 18:32:16 UTC, Lewis wrote:
> import std.random;
> import std.stdio;
>
> int[4] testfunc(int num) @nogc
> {
>     return [0, 1, num, 3];
> }
>
> int main()
> {
>     int[4] arr = testfunc(uniform(0, 15));
>     writeln(arr);
>     return 0;
> }
>
> I've read a bunch of stuff that seems to indicate that array literals are always heap-allocated, even when being used to populate a static array.

On the contrary, when initializing static arrays, allocation is not needed.
Note that what's *conceptually* happening in testfunc is this:

>int[4] testfunc(int num) @nogc
>{
>    typeof(return) result = [0, 1, num, 3];
>    return result;
>}

i.e. the type and size of the storage is known beforehand, all there is to do is copy the elements:

000000000044e528 <@nogc int[4] test.testfunc(int)>:
  44e528:       55                      push   %rbp
  44e529:       48 8b ec                mov    %rsp,%rbp
  44e52c:       48 83 ec 10             sub    $0x10,%rsp
  44e530:       48 89 7d f8             mov    %rdi,-0x8(%rbp)
  44e534:       c7 07 00 00 00 00       movl   $0x0,(%rdi)      # 0 goes at offset 0
  44e53a:       c7 47 04 01 00 00 00    movl   $0x1,0x4(%rdi)   # 1 at offset 4
  44e541:       89 77 08                mov    %esi,0x8(%rdi)   # parameter at offset 8
  44e544:       c7 47 0c 03 00 00 00    movl   $0x3,0xc(%rdi)   # 3 at offset 12
  44e54b:       48 8b 45 f8             mov    -0x8(%rbp),%rax
  44e54f:       c9                      leaveq
  44e550:       c3                      retq

> Is all the old stuff I was reading just out-of-date now?

Where exactly did you read that initialization of a static array requires an allocation? That source should be abolished... errrm... corrected!
May 13, 2017
On Saturday, 13 May 2017 at 18:32:16 UTC, Lewis wrote:
> import std.random;
> import std.stdio;
>
> int[4] testfunc(int num) @nogc
> {
>     return [0, 1, num, 3];
> }
>
> int main()
> {
>     int[4] arr = testfunc(uniform(0, 15));
>     writeln(arr);
>     return 0;
> }
>
> I've read a bunch of stuff that seems to indicate that array literals are always heap-allocated, even when being used to populate a static array. However, testfunc() above compiles as @nogc. This would indicate to me that D does the smart thing and avoids a heap allocation for an array literal being used to populate a static array. Is all the old stuff I was reading just out-of-date now?

It's just out of date. Can't remember the version, but this did use to allocate. It doesn't any more. But only for this case. In most cases it does allocate.

-Steve

May 13, 2017
On Saturday, 13 May 2017 at 18:32:16 UTC, Lewis wrote:
> import std.random;
> import std.stdio;
>
> int[4] testfunc(int num) @nogc
> {
>     return [0, 1, num, 3];
> }
>
> int main()
> {
>     int[4] arr = testfunc(uniform(0, 15));
>     writeln(arr);
>     return 0;
> }
>
> I've read a bunch of stuff that seems to indicate that array literals are always heap-allocated, even when being used to populate a static array. However, testfunc() above compiles as @nogc. This would indicate to me that D does the smart thing and avoids a heap allocation for an array literal being used to populate a static array. Is all the old stuff I was reading just out-of-date now?

1D arrays it doesn't, 2D or higher it does.
May 14, 2017
On Saturday, 13 May 2017 at 19:22:09 UTC, Steven Schveighoffer wrote:
> It's just out of date. Can't remember the version, but this did use to allocate. It doesn't any more. But only for this case. In most cases it does allocate.

Okay cool, that's good to hear. For reference the most recent place I remember seeing this was http://stackoverflow.com/questions/6751575/how-to-initialise-static-arrays-in-d-without-a-gc-allocation (although I've definitely seen others in the past). I'll add an answer to the SO question to clarify that this is no longer an issue.

Thanks all!


May 14, 2017
On Sunday, 14 May 2017 at 01:15:03 UTC, Lewis wrote:
> On Saturday, 13 May 2017 at 19:22:09 UTC, Steven Schveighoffer wrote:
>> It's just out of date. Can't remember the version, but this did use to allocate. It doesn't any more. But only for this case. In most cases it does allocate.
>
> Okay cool, that's good to hear. For reference the most recent place I remember seeing this was http://stackoverflow.com/questions/6751575/how-to-initialise-static-arrays-in-d-without-a-gc-allocation (although I've definitely seen others in the past). I'll add an answer to the SO question to clarify that this is no longer an issue.
>
> Thanks all!

You could also use something like this:

----
auto s(T, size_t n)(T[n] arr)
{
    return arr;
}

auto is = [1, 2, 3].s; // stack allocated
----

I use it whenever I work with D.
May 14, 2017
On Sunday, 14 May 2017 at 01:15:03 UTC, Lewis wrote:
> On Saturday, 13 May 2017 at 19:22:09 UTC, Steven Schveighoffer wrote:
>> It's just out of date. Can't remember the version, but this did use to allocate. It doesn't any more. But only for this case. In most cases it does allocate.
>
> Okay cool, that's good to hear. For reference the most recent place I remember seeing this was http://stackoverflow.com/questions/6751575/how-to-initialise-static-arrays-in-d-without-a-gc-allocation (although I've definitely seen others in the past). I'll add an answer to the SO question to clarify that this is no longer an issue.
>
> Thanks all!

It may allocate if it is returned. I think it elided for one caller because it constructs into the callers stack frame but only if the length of all return path are the same length. For 2D or higher it always allocates, i think.
May 14, 2017
On 05/14/2017 01:57 AM, Nicholas Wilson wrote:
> 1D arrays it doesn't, 2D or higher it does.

What do you mean? This works just fine as well:

----
import std.random;
import std.stdio;

int[2][2] testfunc(int num) @nogc
{
    return [[0, 1], [num, 3]];
}

int main()
{
    int[2][2] arr = testfunc(uniform(0, 15));
    writeln(arr);
    return 0;
}
----
May 14, 2017
On Sunday, 14 May 2017 at 10:18:40 UTC, ag0aep6g wrote:
> On 05/14/2017 01:57 AM, Nicholas Wilson wrote:
>> 1D arrays it doesn't, 2D or higher it does.
>
> What do you mean? This works just fine as well:
>
> ----
> import std.random;
> import std.stdio;
>
> int[2][2] testfunc(int num) @nogc
> {
>     return [[0, 1], [num, 3]];
> }
>
> int main()
> {
>     int[2][2] arr = testfunc(uniform(0, 15));
>     writeln(arr);
>     return 0;
> }
> ----

dynamic array literals is what I meant.
May 14, 2017
On 05/14/2017 01:40 PM, Nicholas Wilson wrote:
> dynamic array literals is what I meant.

I don't follow. Can you give an example in code?
« First   ‹ Prev
1 2