digitalmars.D.bugs - [Issue 14451] New: static-foreach uses huge stack for no reason
- via Digitalmars-d-bugs (75/75) Apr 16 2015 https://issues.dlang.org/show_bug.cgi?id=14451
https://issues.dlang.org/show_bug.cgi?id=14451 Issue ID: 14451 Summary: static-foreach uses huge stack for no reason Product: D Version: D2 Hardware: x86_64 OS: Linux Status: NEW Severity: major Priority: P1 Component: DMD Assignee: nobody puremagic.com Reporter: tomerfiliba gmail.com Using static foreach (on a compile-time known range) basically expands the code block so many times. That's excellent, except that variables declared inside the foreach-body are not scoped properly, which causes needless, huge stack allocation. Consider the following snippet: ================================================ import std.traits; struct S {ubyte a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z;} string[] staticForeach1() { string[] arr; foreach(string name; __traits(allMembers, S)) { ulong[100] x; arr ~= name; } return arr; } string[] staticForeach2() { string[] arr; foreach(string name; __traits(allMembers, S)) { (){ ulong[100] x; arr ~= name; }(); } return arr; } ================================================ The first version compiles to Dump of assembler code for function staticForeach1: 0x0000000000426170 <+0>: push %rbp 0x0000000000426171 <+1>: mov %rsp,%rbp 0x0000000000426174 <+4>: sub $0x52f8,%rsp <<<<< 0x000000000042617b <+11>: push %rbx 0x000000000042617c <+12>: movq $0x0,-0x52f0(%rbp) 0x0000000000426187 <+23>: movq $0x0,-0x52e8(%rbp) requiring over 20K of stack space. The second version compiles to Dump of assembler code for function staticForeach2: 0x0000000000426c48 <+0>: push %rbp 0x0000000000426c49 <+1>: mov %rsp,%rbp 0x0000000000426c4c <+4>: sub $0x10,%rsp <<<<< 0x0000000000426c50 <+8>: movq $0x0,-0x10(%rbp) 0x0000000000426c58 <+16>: movq $0x0,-0x8(%rbp) 0x0000000000426c60 <+24>: mov %rbp,%rdi 0x0000000000426c63 <+27>: callq 0x426d40 <staticForeach2FZ9__lambda1MFNbNfZv> 0x0000000000426c68 <+32>: mov %rbp,%rdi 0x0000000000426c6b <+35>: callq 0x426db8 <staticForeach2FZ9__lambda2MFNbNfZv> 0x0000000000426c70 <+40>: mov %rbp,%rdi requiring only 16 bytes. I tried adding more scoping braces inside the foreach, e.g., foreach(string name; __traits(allMembers, S)) { { ulong[100] x; arr ~= name; } } but anything other than actually invoking a separate function does not work. Since I'm using fibers with small stacks, this is a real issue for me. I can usually find workarounds (as described here), but there's no reason why so much stack be wasted here. --
Apr 16 2015