May 20, 2017
On Sat, May 20, 2017 at 07:53:58AM +0000, Stefan Koch via Digitalmars-d wrote:
> On Saturday, 20 May 2017 at 07:02:10 UTC, Walter Bright wrote:
> > 
> > Also, have a GC makes CTFE real nice.
> 
> Having to implement a GC for newCTFE won't be nice though :o)
> I agree though being able to allocate memory makes ctfe much more
> useful then it would otherwise be.

I think we might be able to get away without implementing a GC for newCTFE.  All you need is a memory pool allocator, i.e., a bump-the-pointer algorithm to a block of memory (or maybe a linked list of blocks if we need to make it growable) allocated when you enter CTFE, then upon exiting CTFE, copy out the return value(s) and free the entire pool.

As long as we don't anticipate CTFE code that requires massive amounts of allocation / deallocation before producing a result, this ought to be good enough.


T

-- 
What do you get if you drop a piano down a mineshaft? A flat minor.
May 20, 2017
On Sat, May 20, 2017 at 03:05:44PM +0000, Stefan Koch via Digitalmars-d wrote:
> On Saturday, 20 May 2017 at 14:59:37 UTC, Ola Fosheim Grøstad wrote:
> > On Saturday, 20 May 2017 at 13:36:14 UTC, Stefan Koch wrote:
> > > unions and other ABI-related things will be tricky.
> > 
> > Isn't the unions issue quite easily solved by tagging behind the scenes?
> 
> Ah tagging behind the scene is an option, it comes with runtime cost though.  And tagging would disallow the tricky and very common usecase of overlaying and int and a float.
> 
> This I understand, is heavily used.

We only need this for floating-point operations.  The current CTFE engine already special-cases floats for repainting, so we could potentially just special-case unions involving floats and leave everything else unsupported.  Supporting unions in CTFE can be a bear.


T

-- 
Computers aren't intelligent; they only think they are.
May 20, 2017
On Saturday, May 20, 2017 12:34:09 PM PDT H. S. Teoh via Digitalmars-d wrote:
> On Sat, May 20, 2017 at 07:53:58AM +0000, Stefan Koch via Digitalmars-d
wrote:
> > On Saturday, 20 May 2017 at 07:02:10 UTC, Walter Bright wrote:
> > > Also, have a GC makes CTFE real nice.
> >
> > Having to implement a GC for newCTFE won't be nice though :o)
> > I agree though being able to allocate memory makes ctfe much more
> > useful then it would otherwise be.
>
> I think we might be able to get away without implementing a GC for newCTFE.  All you need is a memory pool allocator, i.e., a bump-the-pointer algorithm to a block of memory (or maybe a linked list of blocks if we need to make it growable) allocated when you enter CTFE, then upon exiting CTFE, copy out the return value(s) and free the entire pool.
>
> As long as we don't anticipate CTFE code that requires massive amounts of allocation / deallocation before producing a result, this ought to be good enough.

Well, from the perspective of ther user's code, there really isn't any difference. They can allocate memory with new, and the compiler takes care of managing the memory.

- Jonathan M Davis

May 21, 2017
On Saturday, 20 May 2017 at 13:06:01 UTC, Jonathan M Davis wrote:
> ...

Let's take the CTFE discussion to a different thread
May 22, 2017
On Saturday, 20 May 2017 at 02:05:21 UTC, Jonathan M Davis wrote:
> What we would probably need would be to change msg is a function which generates a message so that derived classes can override that rather than passing a message string.

Further to Moritz's reply showing the existing toString overload taking a delegate. This delegate is not @nogc. Otherwise I was thinking of doing something like this:

//FIXME: uniqueToString should return @nogc UniquePtr!(const char[])
import std.conv;
alias uniqueToString = to!(const char[]);

class MessageEx(E, sinkArgs...) : E
{
    this(A...)(A args)
    {
        super(args);
    }

    //FIXME: delegate not @nogc
    /*@nogc*/ override void toString(scope void delegate(in char[]) sink) const
    {
        foreach (a; sinkArgs)
            sink(uniqueToString(a));
    }
}

unittest
{
    auto x = 7;
    throw new MessageEx!(Exception, "x = ", x)(null);
}

The result of uniqueToString would free any memory allocated after the call to sink.

May 22, 2017
On Saturday, 20 May 2017 at 09:35:34 UTC, Stanislav Blinov wrote:
> On Saturday, 20 May 2017 at 02:25:45 UTC, Walter Bright wrote:
>>   void foo(scope string s);
>
> string s = callCAPIAndAllocateString();
> foo(s ~ "abc");
>
> What will happen? The compiler will generate different code? Won't compile? The former means invisible performance gap. The latter means an unpleasant surprise. Neither are good. Do we really need such special cases?

It's no different from when s is GC allocated, s[] has to be copied for the concatenation. I'm not sure how Walter wants to lower this, but maybe it could use a region/stacked allocator. That could mean allocation in constant time when the region is already big enough, and deallocation would be constant time (except if freeing an unused region ahead of the current region).
May 23, 2017
On Friday, 19 May 2017 at 15:45:28 UTC, Mike Parker wrote:
> Extensive discussion of this DIP has already taken place in two threads, both linked from the document. You may find it beneficial to skim through those threads before posting any feedback here.
>
> Thanks in advance to all who participate.
>
> Destroy!

The proposal is a very mechanical fix, throwing several special cases at one specific problem.
Why does it have to be refcounted? Seems like there is only ever one reference to the current exception (the catch variable).
The only thing that seems necessary is to require scope on catch variable declarations, so that people do not escape the class reference, then this info might be used by the runtime to free exception objects after the catch handler is done.

Amaury put a bit more words into that.
http://forum.dlang.org/post/gtqsojgqqaorubcsneie@forum.dlang.org

Has staticError been considered? It has a potential issue with multiple nested exceptions, but otherwise works fine.
https://github.com/dlang/druntime/blob/bc832b18430ce1c85bf2dded07bbcfe348ff0813/src/core/exception.d#L683
May 24, 2017
On Monday, 22 May 2017 at 12:00:30 UTC, Nick Treleaven wrote:
> //FIXME: uniqueToString should return @nogc UniquePtr!(const char[])
> import std.conv;
> alias uniqueToString = to!(const char[]);
>
> class MessageEx(E, sinkArgs...) : E
> {
>     this(A...)(A args)
>     {
>         super(args);
>     }
>
>     //FIXME: delegate not @nogc
>     /*@nogc*/ override void toString(scope void delegate(in char[]) sink) const
>     {
>         foreach (a; sinkArgs)
>             sink(uniqueToString(a));
>     }
> }
>
> unittest
> {
>     auto x = 7;
>     throw new MessageEx!(Exception, "x = ", x)(null);
> }
>
> The result of uniqueToString would free any memory allocated after the call to sink.

Heh, I actually ran into this problem earlier today and just saw this post https://issues.dlang.org/show_bug.cgi?id=17420

Weird coincidence.
May 24, 2017
On Tuesday, 23 May 2017 at 22:40:43 UTC, Martin Nowak wrote:
> The proposal is a very mechanical fix, throwing several special cases at one specific problem.
> Why does it have to be refcounted? Seems like there is only ever one reference to the current exception (the catch variable).
> The only thing that seems necessary is to require scope on catch variable declarations, so that people do not escape the class reference, then this info might be used by the runtime to free exception objects after the catch handler is done.
>
> Amaury put a bit more words into that.
> http://forum.dlang.org/post/gtqsojgqqaorubcsneie@forum.dlang.org
>
> Has staticError been considered? It has a potential issue with multiple nested exceptions, but otherwise works fine.
> https://github.com/dlang/druntime/blob/bc832b18430ce1c85bf2dded07bbcfe348ff0813/src/core/exception.d#L683

I'm trying to understand your and Amaury's point. Normally, when you say `new` you get memory from the GC allocator. The @nogc attribute is supposed to prevent this, if I understand it correctly. Are you saying that `@nogc` as such is misconceived, because what a good language feature should really be doing is identifying and preventing new memory that _can't_ be deterministically destroyed? Is the problem here with the @nogc attribute? Because I think Walter's goal with this DIP is to make it so that you can put @nogc on _called_ functions that throw using `new`. Whereas your solution is to ignore that `new Exception` allocation, on account of the fact that you can deterministically destroy the Exception, provided you use `scope` catch blocks at, or above, the call site. Your solution might actually have its priorities straight, and `@nogc` may be designed badly because it clumps all GC allocations into one big basket. However, getting new memory from the GC still could trigger a collection cycle, which is what @nogc was created for, and simply knowing that you can reliably destroy the allocated memory doesn't change that.

Thus, if I understand correctly, you and Amaury are arguing that `@nogc` as currently designed is a false goal to be chasing, that the more important goal is memory that can be deterministically destroyed, and therefore it distresses you that the language may be altered to chase the false prize of `@nogc` everywhere, instead of focusing on a real prize worth attaining?

May 24, 2017
On 5/23/2017 3:40 PM, Martin Nowak wrote:
> Why does it have to be refcounted? Seems like there is only ever one reference to the current exception (the catch variable).

Rethrowing the catch variable makes for 2 references.


> Has staticError been considered? It has a potential issue with multiple nested exceptions, but otherwise works fine.
> https://github.com/dlang/druntime/blob/bc832b18430ce1c85bf2dded07bbcfe348ff0813/src/core/exception.d#L683 

Doesn't work for chained exceptions.