digitalmars.D.learn - Do array literals still always allocate?
- Lewis (19/19) May 13 2017 import std.random;
- Stanislav Blinov (25/46) May 13 2017 On the contrary, when initializing static arrays, allocation is
- Steven Schveighoffer (5/24) May 13 2017 It's just out of date. Can't remember the version, but this did
- Lewis (6/9) May 13 2017 Okay cool, that's good to hear. For reference the most recent
- Namespace (10/19) May 14 2017 You could also use something like this:
- Nicholas Wilson (5/14) May 14 2017 It may allocate if it is returned. I think it elided for one
- Nicholas Wilson (2/21) May 13 2017 1D arrays it doesn't, 2D or higher it does.
- ag0aep6g (16/17) May 14 2017 What do you mean? This works just fine as well:
- Nicholas Wilson (2/19) May 14 2017 dynamic array literals is what I meant.
- ag0aep6g (2/3) May 14 2017 I don't follow. Can you give an example in code?
- Eugene Wissner (7/10) May 14 2017 void main()
- ag0aep6g (2/8) May 14 2017 Sure, but Nicholas said 1D arrays behave different from 2D arrays.
- Nicholas Wilson (5/16) May 14 2017 LDC is able to promote those to alloca, not sure about DMD or its
- Steven Schveighoffer (15/38) May 15 2017 dynamic array literals allocate most of the time. The one time they
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) 0 goes at offset 0 1 at offset 4 parameter at offset 8 3 at offset 12 44e54b: 48 8b 45 f8 mov -0x8(%rbp),%rax 44e54f: c9 leaveq 44e550: c3 retqIs 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 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-wit out-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 13 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: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.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-wit out-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 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.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-wit out-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 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 13 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:dynamic array literals is what I meant.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 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?
May 14 2017
On Sunday, 14 May 2017 at 11:45:12 UTC, ag0aep6g wrote:On 05/14/2017 01:40 PM, Nicholas Wilson wrote:void main() { ubyte[] arr = [ 1, 2, 3, 4, 5 ]; assert(arr == [ 1, 2, 3, 4, 5 ]); } Both, assignment and comparison, allocate.dynamic array literals is what I meant.I don't follow. Can you give an example in code?
May 14 2017
On 05/14/2017 02:02 PM, Eugene Wissner wrote:void main() { ubyte[] arr = [ 1, 2, 3, 4, 5 ]; assert(arr == [ 1, 2, 3, 4, 5 ]); } Both, assignment and comparison, allocate.Sure, but Nicholas said 1D arrays behave different from 2D arrays.
May 14 2017
On Sunday, 14 May 2017 at 12:02:03 UTC, Eugene Wissner wrote:On Sunday, 14 May 2017 at 11:45:12 UTC, ag0aep6g wrote:LDC is able to promote those to alloca, not sure about DMD or its interaction with nogc. see https://github.com/ldc-developers/ldc/blob/master/gen/passes/GarbageCo lect2Stack.cpp#L832 for the details.On 05/14/2017 01:40 PM, Nicholas Wilson wrote:void main() { ubyte[] arr = [ 1, 2, 3, 4, 5 ]; assert(arr == [ 1, 2, 3, 4, 5 ]); } Both, assignment and comparison, allocate.dynamic array literals is what I meant.I don't follow. Can you give an example in code?
May 14 2017
On 5/14/17 7:40 AM, Nicholas Wilson wrote:On Sunday, 14 May 2017 at 10:18:40 UTC, ag0aep6g wrote:dynamic array literals allocate most of the time. The one time they don't is the specialized case of initializing a static array, I think of any dimension. However, to the OP's point, they *did* allocate up until a certain version, even when initializing a static array. That is: int[2] x = [1, 2]; used to allocate a dynamic array on the heap, and then copy the data into x (and leave the allocated data for the GC). Now it just populates x without allocating. LDC might be smarter, and take more valid shortcuts, so that is good. But in general you can expect array literals to allocate when not used as static array initializers. -SteveOn 05/14/2017 01:57 AM, Nicholas Wilson wrote:dynamic array literals is what I meant.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 15 2017