Jump to page: 1 2
Thread overview
[Issue 18788] static arrays with a length specified at runtime should dynamically allocate on the stack
Apr 21, 2018
Nicholas Wilson
Apr 21, 2018
Mike Franklin
Apr 21, 2018
Adam D. Ruppe
Apr 21, 2018
Jonathan M Davis
Apr 22, 2018
Mike Franklin
Aug 12, 2018
Mike Franklin
Aug 14, 2018
ZombineDev
Aug 14, 2018
Walter Bright
Aug 15, 2018
Seb
Aug 16, 2018
anonymous4
Dec 17, 2022
Iain Buclaw
April 21, 2018
https://issues.dlang.org/show_bug.cgi?id=18788

Nicholas Wilson <iamthewilsonator@hotmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |iamthewilsonator@hotmail.co
                   |                            |m

--- Comment #1 from Nicholas Wilson <iamthewilsonator@hotmail.com> ---
this is the role of std.experimental.allocator.StackFront and friends (e.g. InSituRegion), there is probably room for runtime choice of StackFront and InSituRegion such that there is no stack allocation if the length exceeds the InSituRegion size.

Perhaps the compiler should point users to this once it is made non-experimental, but this should not be a language feature as it is unsafe and may inadvertently blow the stack.

--
April 21, 2018
https://issues.dlang.org/show_bug.cgi?id=18788

--- Comment #2 from Mike Franklin <slavo5150@yahoo.com> ---
Yes it is unsafe, but not any less safe than

void unsafeRecursion(size_t iterations)
{
    if(iterations)
    {
        byte[256] buffer;
        unsafeRecursion(--iterations);
    }
}

As a compromise it could be restricted to @system code.

--
April 21, 2018
https://issues.dlang.org/show_bug.cgi?id=18788

Adam D. Ruppe <destructionator@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |destructionator@gmail.com

--- Comment #3 from Adam D. Ruppe <destructionator@gmail.com> ---
I'd actually just like to redefine `new` to mean the compiler is free to stack allocate it when it can prove the lifetime does not exceed that of the function (and the scope annotations can hint/prove/override this, as it already does for classes[!])

--
April 21, 2018
https://issues.dlang.org/show_bug.cgi?id=18788

Jonathan M Davis <issues.dlang@jmdavisProg.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |issues.dlang@jmdavisProg.co
                   |                            |m

--- Comment #4 from Jonathan M Davis <issues.dlang@jmdavisProg.com> ---
(In reply to Adam D. Ruppe from comment #3)
> I'd actually just like to redefine `new` to mean the compiler is free to stack allocate it when it can prove the lifetime does not exceed that of the function (and the scope annotations can hint/prove/override this, as it already does for classes[!])

Well, in principle, with DIP 1000, the case where scope on classes allocates the class on the stack simply becomes a compiler optimization rather than the specific purpose of scope (rather, the purpose of scope at that point is to give the compiler the information it needs to guarantee that no pointers or references or whatnot to the variable or object escape). As such, I don't see any reason why that optimization couldn't be expanded to cover other types allocated with new.

--
April 22, 2018
https://issues.dlang.org/show_bug.cgi?id=18788

--- Comment #5 from Mike Franklin <slavo5150@yahoo.com> ---
Another way of achieving the same result would be to make a `scope`d dynamic array allocate on the stack

---
class C { }

void main()
{
    scope C c = new C();       // `c` is allocated on the stack
    scope int[] i = [1, 2, 3]; // `i` is inconsistently allocated on the heap
}

I think this should be consistent between classes and dynamic arrays; `i` should be allocated on the stack, and appending to it should allocate `realloc`ate it on the stack.

--
August 12, 2018
https://issues.dlang.org/show_bug.cgi?id=18788

Mike Franklin <slavo5150@yahoo.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           See Also|                            |https://issues.dlang.org/sh
                   |                            |ow_bug.cgi?id=19159

--
August 14, 2018
https://issues.dlang.org/show_bug.cgi?id=18788

ZombineDev <petar.p.kirov@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |petar.p.kirov@gmail.com

--- Comment #6 from ZombineDev <petar.p.kirov@gmail.com> ---
LDC has a pass[1] that does escape analysis for class instances and dynamic arrays and stack allocates them when possible. Sadly they do this on the LLVM IR level, so their solution can't be easily upstream-ed to dmd's frontend.

Static arrays can't have their length specified at run-time, as it's part of their type. (Just like you can't specify template arguments at run-time. The only thing resembling providing compile-time arguments at run-time is simply instantiating various alternatives at compile-time and selecting one of them at run-time.) What you can do is an array-like struct that wraps alloca. Compile-time safety is out of the question, but it could try to check if it can fit in the remaining stack space minus a several pages. Even so, it would be quite brittle and heavily dependent on platform and run-time specifics (e.g. querying the fiber stack size, when not running on the native thread stack).

AFAIK, `scope` is currently inferred only for value types (scalars and static arrays) with -dip1000. Perhaps the inference can be extended to cover dynamic arrays and classes as well.

One thing that we must be careful about is that the array memory management [2] built on top of the GC has certain assumptions like looking for block metadata (e.g. array capacity) on its heap. These assumptions may fail if the compiler promotes the array on the stack. But if all of druntime's lifetime code is template-ized, in theory the compiler should be able to see through it and detect that the array .length getter property is trivially scope-friendly, while the setter is not. Don't know how .capacity should be handled.

[1]: https://github.com/ldc-developers/ldc/blob/16f37466fe918e0824a3b2db239ba5a7ce5a33cc/gen/passes/GarbageCollect2Stack.cpp

[2]: https://github.com/dlang/druntime/blob/bb7e1c0991c0ae43520e67c91d0b7b0d8d315d2e/src/rt/lifetime.d#L1442

--
August 14, 2018
https://issues.dlang.org/show_bug.cgi?id=18788

Walter Bright <bugzilla@digitalmars.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |bugzilla@digitalmars.com

--- Comment #7 from Walter Bright <bugzilla@digitalmars.com> ---
(In reply to Mike Franklin from comment #0)
>     char[newLen + 1] buf;     // Error: variable newLen cannot be read at
> compile time

I suspect the correct way to handle this would be:

    scope char[] buf = new char[newlen + 1];

The `scope` will ensure `buf` does not escape the stack frame, and so the compiler can allocate it on the stack.

This is how:

    class C { ... }
    scope C c = new C();

works today.

--
August 15, 2018
https://issues.dlang.org/show_bug.cgi?id=18788

Seb <greensunny12@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |greensunny12@gmail.com

--
August 16, 2018
https://issues.dlang.org/show_bug.cgi?id=18788

anonymous4 <dfj1esp02@sneakemail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |betterC, performance
           See Also|                            |https://issues.dlang.org/sh
                   |                            |ow_bug.cgi?id=16037

--- Comment #8 from anonymous4 <dfj1esp02@sneakemail.com> ---
(In reply to Mike Franklin from comment #5)
> Another way of achieving the same result would be to make a `scope`d dynamic array allocate on the stack
> 
> ---
> class C { }
> 
> void main()
> {
>     scope C c = new C();       // `c` is allocated on the stack
>     scope int[] i = [1, 2, 3]; // `i` is inconsistently allocated on the heap
> }
Ideally yes, but see discussion in issue 16037.

--
« First   ‹ Prev
1 2