October 21, 2013
On Sunday, 20 October 2013 at 14:25:37 UTC, bearophile wrote:
> More discussions about variable-sized stack-allocated arrays in C++, it seems there is no yet a consensus:
>
> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3810.pdf
>
> I'd like variable-sized stack-allocated arrays in D.
>
> Bye,
> bearophile

I think that is a job for the optimizer. Consider cases like :

auto foo() {
    return new Foo();
}

void bar() {
   auto f = foo();
   f.someMethod();
}

This is an incredibly common pattern, and it won't be possible to optimize it via added language design without dramatic increase in language complexity.

However, once the inliner is passed, you'll end up with something like :
auto foo() {
    return new Foo();
}

void bar() {
   auto f = new Foo();
   f.someMethod();
}

And if the optimizer is aware of GC calls (LDC is already aware of them, even if only capable of limited optimizations, it is already a good start and show the feasibility of the idea).

Obviously Foo is a struct or an class here, but that is the exact same problem as for arrays.
October 21, 2013
On 10/21/2013 07:53 PM, Iain Buclaw wrote:
> On 21 October 2013 18:42, Walter Bright <newshound2@digitalmars.com> wrote:
>> On 10/21/2013 9:24 AM, Iain Buclaw wrote:
>>>
>>> http://dpaste.dzfl.pl/3e333df6
>>>
>>> PS:  Walter, looks the above causes an ICE in DMD?
>>
>>
>> All ICE's should be filed in bugzilla:
>>
>> http://d.puremagic.com/issues/show_bug.cgi?id=11315
>>
>
> I've told enough people to raise bugs in GDC to know this.  My
> intention wasn't to find a bug in DMD though when I pasted that link.
> ;-)
>
> I was more curious what LDC does if it stack allocates array literals
> assigned to static arrays in that program.  My guess is that the
> dynamic array will get the address of the stack allocated array
> literal, and it's values will be lost after calling fill();
>
> If so, this is another bug that needs to be filled and fixed.
>

Why? AFAICS it is the expected behaviour in any case.
October 21, 2013
On 21 October 2013 21:24, Timon Gehr <timon.gehr@gmx.ch> wrote:
> On 10/21/2013 07:53 PM, Iain Buclaw wrote:
>>
>> On 21 October 2013 18:42, Walter Bright <newshound2@digitalmars.com> wrote:
>>>
>>> On 10/21/2013 9:24 AM, Iain Buclaw wrote:
>>>>
>>>>
>>>> http://dpaste.dzfl.pl/3e333df6
>>>>
>>>> PS:  Walter, looks the above causes an ICE in DMD?
>>>
>>>
>>>
>>> All ICE's should be filed in bugzilla:
>>>
>>> http://d.puremagic.com/issues/show_bug.cgi?id=11315
>>>
>>
>> I've told enough people to raise bugs in GDC to know this.  My intention wasn't to find a bug in DMD though when I pasted that link. ;-)
>>
>> I was more curious what LDC does if it stack allocates array literals assigned to static arrays in that program.  My guess is that the dynamic array will get the address of the stack allocated array literal, and it's values will be lost after calling fill();
>>
>> If so, this is another bug that needs to be filled and fixed.
>>
>
> Why? AFAICS it is the expected behaviour in any case.

It's an assignment to a dynamic array, so it should invoke the GC and do a _d_arraycopy.


-- 
Iain Buclaw

*(p < e ? p++ : p) = (c & 0x0f) + '0';
October 21, 2013
On 10/21/2013 10:32 PM, Iain Buclaw wrote:
> On 21 October 2013 21:24, Timon Gehr <timon.gehr@gmx.ch> wrote:
>> On 10/21/2013 07:53 PM, Iain Buclaw wrote:
>>>
>>> On 21 October 2013 18:42, Walter Bright <newshound2@digitalmars.com>
>>> wrote:
>>>>
>>>> On 10/21/2013 9:24 AM, Iain Buclaw wrote:
>>>>>
>>>>>
>>>>> http://dpaste.dzfl.pl/3e333df6
>>>>>
>>>>> PS:  Walter, looks the above causes an ICE in DMD?
>>>>
>>>>
>>>>
>>>> All ICE's should be filed in bugzilla:
>>>>
>>>> http://d.puremagic.com/issues/show_bug.cgi?id=11315
>>>>
>>>
>>> I've told enough people to raise bugs in GDC to know this.  My
>>> intention wasn't to find a bug in DMD though when I pasted that link.
>>> ;-)
>>>
>>> I was more curious what LDC does if it stack allocates array literals
>>> assigned to static arrays in that program.  My guess is that the
>>> dynamic array will get the address of the stack allocated array
>>> literal, and it's values will be lost after calling fill();
>>>
>>> If so, this is another bug that needs to be filled and fixed.
>>>
>>
>> Why? AFAICS it is the expected behaviour in any case.
>
> It's an assignment to a dynamic array, so it should invoke the GC and
> do a _d_arraycopy.
>
>

This code:

int[] x;
int[3] y;

x = y = [1,2,3];

Is equivalent to this code:

int[] x;
int[3] y;

y = [1,2,3];
x = y; // <-- here

Are you saying the line marked with "here" should perform an implicit allocation and copy the contents of y to the heap?


October 21, 2013
On 21 October 2013 21:41, Timon Gehr <timon.gehr@gmx.ch> wrote:
> On 10/21/2013 10:32 PM, Iain Buclaw wrote:
>>
>> On 21 October 2013 21:24, Timon Gehr <timon.gehr@gmx.ch> wrote:
>>>
>>> On 10/21/2013 07:53 PM, Iain Buclaw wrote:
>>>>
>>>>
>>>> On 21 October 2013 18:42, Walter Bright <newshound2@digitalmars.com> wrote:
>>>>>
>>>>>
>>>>> On 10/21/2013 9:24 AM, Iain Buclaw wrote:
>>>>>>
>>>>>>
>>>>>>
>>>>>> http://dpaste.dzfl.pl/3e333df6
>>>>>>
>>>>>> PS:  Walter, looks the above causes an ICE in DMD?
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> All ICE's should be filed in bugzilla:
>>>>>
>>>>> http://d.puremagic.com/issues/show_bug.cgi?id=11315
>>>>>
>>>>
>>>> I've told enough people to raise bugs in GDC to know this.  My intention wasn't to find a bug in DMD though when I pasted that link. ;-)
>>>>
>>>> I was more curious what LDC does if it stack allocates array literals assigned to static arrays in that program.  My guess is that the dynamic array will get the address of the stack allocated array literal, and it's values will be lost after calling fill();
>>>>
>>>> If so, this is another bug that needs to be filled and fixed.
>>>>
>>>
>>> Why? AFAICS it is the expected behaviour in any case.
>>
>>
>> It's an assignment to a dynamic array, so it should invoke the GC and do a _d_arraycopy.
>>
>>
>
> This code:
>
> int[] x;
> int[3] y;
>
> x = y = [1,2,3];
>
> Is equivalent to this code:
>
> int[] x;
> int[3] y;
>
> y = [1,2,3];
> x = y; // <-- here
>
> Are you saying the line marked with "here" should perform an implicit allocation and copy the contents of y to the heap?
>
>


In GDC, the allocation currently is:

y = [1,2,3];  // <--- here

So it is a safe to not copy.

But yes.  I think a GC memcopy should be occuring, as dynamic arrays aren't passed by value, so are expected to last the lifetime of the reference to the address.


-- 
Iain Buclaw

*(p < e ? p++ : p) = (c & 0x0f) + '0';
October 21, 2013
On Monday, 21 October 2013 at 21:07:46 UTC, Iain Buclaw wrote:
> But yes.  I think a GC memcopy should be occuring, as dynamic arrays
> aren't passed by value, so are expected to last the lifetime of the
> reference to the address.

This doesn't produce a heap copy (neither according to the spec nor to actual DMD/LDC behaviour):

---
void foo() {
    int[3] a;
    int[] b = a;
}
---

Thus, your example will not copy any data either, as due to associativity, it is equivalent to an assignment to y followed by an assignment of y to x. x simply is a slice of the stack-allocated static array.

David
October 21, 2013
On 21 October 2013 22:24, David Nadlinger <code@klickverbot.at> wrote:
> On Monday, 21 October 2013 at 21:07:46 UTC, Iain Buclaw wrote:
>>
>> But yes.  I think a GC memcopy should be occuring, as dynamic arrays aren't passed by value, so are expected to last the lifetime of the reference to the address.
>
>
> This doesn't produce a heap copy (neither according to the spec nor to
> actual DMD/LDC behaviour):
>
> ---
> void foo() {
>     int[3] a;
>     int[] b = a;
> }
> ---
>
> Thus, your example will not copy any data either, as due to associativity, it is equivalent to an assignment to y followed by an assignment of y to x. x simply is a slice of the stack-allocated static array.
>

I know this, but it does deter me against changing gdc over to stack allocating array literals. :-)

I'll mull on it over night.


-- 
Iain Buclaw

*(p < e ? p++ : p) = (c & 0x0f) + '0';
October 21, 2013
On Monday, 21 October 2013 at 21:41:24 UTC, Iain Buclaw wrote:
> I know this, but it does deter me against changing gdc over to stack
> allocating array literals. :-)
>
> I'll mull on it over night.

There is no change in behaviour due to stack-allocating the literal in the static array assignment (or just not emitting it at all), at least if GDC correctly implements slice <- sarray assignment. The dynamic array never "sees" the literal at all, as shown by Timon.

In the general case (i.e. when assigned to dynamic arrays), you obviously can't stack-allocate literals, but I don't think we disagree here.

David
October 21, 2013
On 21 October 2013 22:48, David Nadlinger <code@klickverbot.at> wrote:
> On Monday, 21 October 2013 at 21:41:24 UTC, Iain Buclaw wrote:
>>
>> I know this, but it does deter me against changing gdc over to stack allocating array literals. :-)
>>
>> I'll mull on it over night.
>
>
> There is no change in behaviour due to stack-allocating the literal in the static array assignment (or just not emitting it at all), at least if GDC correctly implements slice <- sarray assignment. The dynamic array never "sees" the literal at all, as shown by Timon.
>
> In the general case (i.e. when assigned to dynamic arrays), you obviously can't stack-allocate literals, but I don't think we disagree here.
>

That we do not.  :o)


-- 
Iain Buclaw

*(p < e ? p++ : p) = (c & 0x0f) + '0';
October 21, 2013
On Monday, 21 October 2013 at 01:48:56 UTC, Walter Bright wrote:
> On 10/20/2013 5:59 PM, Jonathan M Davis wrote:
>> If that paradigm is frequent enough, it might be worth wrapping it in a
>> struct. Then, you'd probably get something like
>>
>> StaticArray!(int, 10) tmp(n);
>> int[] a = tmp[];
>>
>> which used T[10] if n was 10 or less and allocated T[] otherwise. The
>> destructor could then deal with freeing the memory.
>
> Sounds like a good idea - and it should fit in with Andrei's nascent allocator design.

Hmmm, it gave me a weird idea...

void smalloc(T)(ushort n, void function(T[]) statement)
{
  if(n <= 256)
  {
    if(n <= 16)
    {
      T[16] buf = void;
      statement(buf[0..n]);
    }
    else
    {
      T[256] buf = void;
      statement(buf[0..n]);
    }
  }
  else
  {
    if(n <= 4096)
    {
      T[4096] buf = void;
      statement(buf[0..n]);
    }
    else
    {
      T[65536] buf = void;
      statement(buf[0..n]);
    }
  }
}

smalloc(256, (int[] buf)
{
});