Re: Plan for Exceptions and @nogc?

2015-02-19 Thread via Digitalmars-d

On Wednesday, 18 February 2015 at 20:25:07 UTC, Dicebot wrote:

On Wednesday, 18 February 2015 at 18:26:34 UTC, deadalnix wrote:

On Wednesday, 18 February 2015 at 14:46:30 UTC, Dicebot wrote:
From my POV best proposal from last lengthy discussion was to 
enable reference-counted non-gc-heap Exceptions. But that 
needs a language change because RefCounted!T is a struct and 
thus neither can be thrown nor can be part of Throwable class 
hierarchy.




This is not satisfactory. First there is no safe way to 
refcount right now. Second, this has all kind of implication 
for the GC to scan the heap and so on. Finally this do not 
solve the type qualifier problem.


I don't think a language change to do this pay for itself. i 
understand the appeal, as this is probably simpler to 
implement than the alternative, but that is really building 
technical debt.


Right now I don't care for full memory safety or type safety of 
any proposed solution. I will be glad to have any that actually 
works - and I have not heard of any idea that allows to do that 
without language changes. Your push for owned is also hardly 
relevant because exceptions are good examples of data with 
shared / non-determenistic ownership and thus won't benefit 
from it.


Non-deterministic ownership is exactly what the owned concept 
helps with, because it allows to delay deciding on an actual 
management mechanism until it reaches the consumer. When someone 
catches an owned exception, they can then choose to store it in a 
non-owned variable (= making it GC owned), in a ref-counted 
(which then takes ownership), or to not store it at all, in which 
case it will get released automatically when the catch block is 
left. Before that decision is made, it can still be used without 
losing the owned property, by passing it as a scope parameter 
(or storing it in a scope variable).


Re: Plan for Exceptions and @nogc?

2015-02-19 Thread via Digitalmars-d

On Wednesday, 18 February 2015 at 20:47:36 UTC, deadalnix wrote:

On Wednesday, 18 February 2015 at 20:25:07 UTC, Dicebot wrote:
Right now I don't care for full memory safety or type safety 
of any proposed solution. I will be glad to have any that 
actually works - and I have not heard of any idea that allows 
to do that without language changes. Your push for owned is 
also hardly relevant because exceptions are good examples of 
data with shared / non-determenistic ownership and thus won't 
benefit from it.


I think it make sense to require that something thrown to be 
owned. That means ownership can be transferred from one thread 
to the other. That also mean that the compiler can free the 
exception when it goes out of scope, which is what is wanted 
for exception and @nogc to work together.


The invalid operation in @nogc would become promoting owned to 
Tl/shared/immutable rather than not allocating at all.


This has added benefit to allow for way more code to be @nogc, 
and in many cases transfers the GCness of something in the 
caller, which makes for @nogc compatible libraries that can be 
used in both @nogc and gc situation.


If we are gonna add something in the language, it'd better be 
worth it.


+1

Could you take the time to make a concrete proposal? I'll try to 
have another go at `scope`, which is of course deeply linked with 
ownership, and these two things need to work well together. I 
want to avoid proposing something that will later collide with 
your ideas.


Re: Plan for Exceptions and @nogc?

2015-02-19 Thread deadalnix via Digitalmars-d
On Tuesday, 17 February 2015 at 19:03:49 UTC, Chris Williams 
wrote:
Every throwable function call could be assumed to have a typed 
result (even void functions) and if, after the return, the 
caller checks the type and detects that it was an error, 
bubbles that up, then eventually you get to wherever the 
catcher is.


But so basically, the current ABI doesn't support it and 
there's no desire to change it? How do exceptions currently 
happen, if not via some official ABI declaration of how 
throwable methods interact with one another? The 
compiler/linker determines where the catcher is and inserts 
code to cut down the stack and perform a long jump all the way 
back? If so, how do scope statements work?


No problem. in fact this kind of solution is a good fit for 
language where try blocks are rare (say OCaml for instance) as 
you can unwind much faster, while keeping the cost on the fast 
path small.


But that wouldn't be a good fit for D (or even worse for C++) 
because you have unwinding going on (destructor, scope 
statements, ...) which makes for a lot of implicit try blocks.


Re: Plan for Exceptions and @nogc?

2015-02-18 Thread via Digitalmars-d
On Wednesday, 18 February 2015 at 00:54:37 UTC, Chris Williams 
wrote:
I didn't mean it as a solution. As said, I was just looking for 
an intro to the topic, so that I (and others) could 
meaningfully contribute or at least understand the options. 
I'll look up libunwind and, if that has enough info for me to 
grok it, create a wiki page on the subject.


It is a horrible solution developed for the Itanium VLIW 
architecture which is very sensitive to branching. IRRC it 
basically works by looking at the return address on the stack, 
then picking up stack frame information in a global table to 
unwind. It is language agnostic and the language provides a 
personality function to unwind correctly in a language 
dependent manner...


AFAIK, C++ exceptions are copied from the stack to a special 
memory region when unwinding to prevent the memory issues D 
suffers from.


I agree that a fast unwind with stack pointer reset or multiple 
return paths would be much better, but you need to rewrite the 
backend to support it. That's the main issue... the fast path 
argument is just a sorry excuse that literally means that 
exceptions are avoided for common failures in C++. As a result 
you get APIs that are nonuniform.





Re: Plan for Exceptions and @nogc?

2015-02-18 Thread Matthias Bentrup via Digitalmars-d
On Wednesday, 18 February 2015 at 08:13:35 UTC, Ola Fosheim 
Grøstad wrote:
On Wednesday, 18 February 2015 at 00:54:37 UTC, Chris Williams 
wrote:
I didn't mean it as a solution. As said, I was just looking 
for an intro to the topic, so that I (and others) could 
meaningfully contribute or at least understand the options. 
I'll look up libunwind and, if that has enough info for me to 
grok it, create a wiki page on the subject.


It is a horrible solution developed for the Itanium VLIW 
architecture which is very sensitive to branching. IRRC it 
basically works by looking at the return address on the stack, 
then picking up stack frame information in a global table to 
unwind. It is language agnostic and the language provides a 
personality function to unwind correctly in a language 
dependent manner...


AFAIK, C++ exceptions are copied from the stack to a special 
memory region when unwinding to prevent the memory issues D 
suffers from.


I agree that a fast unwind with stack pointer reset or multiple 
return paths would be much better, but you need to rewrite the 
backend to support it. That's the main issue... the fast path 
argument is just a sorry excuse that literally means that 
exceptions are avoided for common failures in C++. As a result 
you get APIs that are nonuniform.


Windows SEH maintains a per-thread linked list of exception 
handlers, but the C++ runtime seems to install only one handler 
at the start of every function and resorts to lookup tables if 
there are multiply try{}s in the function.


If you want to avoid lookup tables, you can of course add/remove 
catchers dynamically whenever you enter/leave a try block, that 
would add a small cost to every try, but avoids the (larger) 
table lookup cost on the catch.


Re: Plan for Exceptions and @nogc?

2015-02-18 Thread deadalnix via Digitalmars-d
On Wednesday, 18 February 2015 at 08:13:35 UTC, Ola Fosheim 
Grøstad wrote:
It is a horrible solution developed for the Itanium VLIW 
architecture which is very sensitive to branching. IRRC it 
basically works by looking at the return address on the stack, 
then picking up stack frame information in a global table to 
unwind. It is language agnostic and the language provides a 
personality function to unwind correctly in a language 
dependent manner...




Which is true, but would be as true without the horrible mention. 
Adjective do not constitute arguments.


I agree that a fast unwind with stack pointer reset or multiple 
return paths would be much better, but you need to rewrite the 
backend to support it. That's the main issue... the fast path 
argument is just a sorry excuse that literally means that 
exceptions are avoided for common failures in C++. As a result 
you get APIs that are nonuniform.


What you agree with is irrelevant if it do not come backed by 
facts.


You can qualify thing as horrible, sorry excuses and so on, 
the only thing it is telling us is that you seems incapable of 
forming a compelling argument and rely on smear instead.


Re: Plan for Exceptions and @nogc?

2015-02-18 Thread Jonathan Marler via Digitalmars-d

On Wednesday, 18 February 2015 at 14:46:30 UTC, Dicebot wrote:
From my POV best proposal from last lengthy discussion was to 
enable reference-counted non-gc-heap Exceptions. But that needs 
a language change because RefCounted!T is a struct and thus 
neither can be thrown nor can be part of Throwable class 
hierarchy.


Any concept that implies that exceptions an be deallocated in 
`catch` block is absolutely unacceptable because it conflicts 
with exception propagation from fibers - a very important piece 
of functionality.


RefCounted Exceptions would work quite nicely.  You are right 
that It will require work on the language to support them but I 
like that solution.


If you don't mind, could you explain why cleaning up exception in 
the catch block would break exception propogation from fibers.  
Are you saying that if you throw inside a catch block and save a 
reference to the exception (in the new exceptions next field), 
that it will create a dangling pointer?


Re: Plan for Exceptions and @nogc?

2015-02-18 Thread via Digitalmars-d

On Wednesday, 18 February 2015 at 17:55:49 UTC, deadalnix wrote:
Which is true, but would be as true without the horrible 
mention. Adjective do not constitute arguments.


And your nonsensical point is?


Re: Plan for Exceptions and @nogc?

2015-02-18 Thread deadalnix via Digitalmars-d
On Wednesday, 18 February 2015 at 09:04:38 UTC, Matthias Bentrup 
wrote:
Windows SEH maintains a per-thread linked list of exception 
handlers, but the C++ runtime seems to install only one handler 
at the start of every function and resorts to lookup tables if 
there are multiply try{}s in the function.


If you want to avoid lookup tables, you can of course 
add/remove catchers dynamically whenever you enter/leave a try 
block, that would add a small cost to every try, but avoids the 
(larger) table lookup cost on the catch.


You want to do this as C++ introduce a ton of implicit finally 
blocks for destructors. If you would setup one everytime you need 
one, you would trash performance in the fast path.


Re: Plan for Exceptions and @nogc?

2015-02-18 Thread deadalnix via Digitalmars-d

On Wednesday, 18 February 2015 at 14:46:30 UTC, Dicebot wrote:
From my POV best proposal from last lengthy discussion was to 
enable reference-counted non-gc-heap Exceptions. But that needs 
a language change because RefCounted!T is a struct and thus 
neither can be thrown nor can be part of Throwable class 
hierarchy.




This is not satisfactory. First there is no safe way to refcount 
right now. Second, this has all kind of implication for the GC to 
scan the heap and so on. Finally this do not solve the type 
qualifier problem.


I don't think a language change to do this pay for itself. i 
understand the appeal, as this is probably simpler to implement 
than the alternative, but that is really building technical debt.


Any concept that implies that exceptions an be deallocated in 
`catch` block is absolutely unacceptable because it conflicts 
with exception propagation from fibers - a very important piece 
of functionality.


Exception propagate the same way between thread, which is even 
worse :)


Re: Plan for Exceptions and @nogc?

2015-02-18 Thread deadalnix via Digitalmars-d
On Wednesday, 18 February 2015 at 18:43:49 UTC, Ola Fosheim 
Grøstad wrote:

On Wednesday, 18 February 2015 at 17:55:49 UTC, deadalnix wrote:
Which is true, but would be as true without the horrible 
mention. Adjective do not constitute arguments.


And your nonsensical point is?


That you have no idea how to argue, and rely on sticking negative 
adjective close to things you don't like in hope that you'll fool 
someone.


This post I'm answering to is more evidence of that.

That's the last answer you'll get from me until you make any 
valuable argument.


Re: Plan for Exceptions and @nogc?

2015-02-18 Thread via Digitalmars-d

On Wednesday, 18 February 2015 at 18:59:03 UTC, deadalnix wrote:
That's the last answer you'll get from me until you make any 
valuable argument.


Excellent! I hope you keep your promise.


Re: Plan for Exceptions and @nogc?

2015-02-18 Thread Dicebot via Digitalmars-d
On Wednesday, 18 February 2015 at 18:02:14 UTC, Jonathan Marler 
wrote:

On Wednesday, 18 February 2015 at 14:46:30 UTC, Dicebot wrote:
From my POV best proposal from last lengthy discussion was to 
enable reference-counted non-gc-heap Exceptions. But that 
needs a language change because RefCounted!T is a struct and 
thus neither can be thrown nor can be part of Throwable class 
hierarchy.


Any concept that implies that exceptions an be deallocated in 
`catch` block is absolutely unacceptable because it conflicts 
with exception propagation from fibers - a very important 
piece of functionality.


RefCounted Exceptions would work quite nicely.  You are right 
that It will require work on the language to support them but I 
like that solution.


It will likely trigger whole load of other issues being totally 
new language concept but so far I am not aware of any better 
proposal.


Of course to truly address @nogc you need also some sort of 
object pool for exceptions instances where those get returned 
upon release - otherwise it would simply move allocations from GC 
heap to plain heap. Which you can do already and does not really 
fix the problem.


But that is a relatively simple library solution that can be 
built if reference counted exception become reality.


If you don't mind, could you explain why cleaning up exception 
in the catch block would break exception propogation from 
fibers.  Are you saying that if you throw inside a catch block 
and save a reference to the exception (in the new exceptions 
next field), that it will create a dangling pointer?


Imagine application like vibe.d which uses fibers to imitate 
blocking API for async operations (we have something similar in 
Sociomantic projects too). Callbacks execute in the context of 
event loop but if any of those throws you want exception trace to 
point to original blocking call that registered callback.


Right now doing this is relatively simple. You catch all 
exception in callbacks and store exception instance in relevant 
fiber-local data. Upon resuming that fiber it checks if there are 
any pending exceptions and re-throws if there is one. There are 
probably more tricky details but basic principle should be like 
this.


Re: Plan for Exceptions and @nogc?

2015-02-18 Thread via Digitalmars-d
On Wednesday, 18 February 2015 at 09:04:38 UTC, Matthias Bentrup 
wrote:
If you want to avoid lookup tables, you can of course 
add/remove catchers dynamically whenever you enter/leave a try 
block, that would add a small cost to every try, but avoids the 
(larger) table lookup cost on the catch.


There are many ways to get better performance than the current 
regime, both dynamic and static approaches, with little execution 
costs, but since most C++ programs don't rely on exceptions where 
speed matters there is little incentive to improve considering 
the complications in the backend. So I don't expect the C++ crowd 
to do anything about it.


As a result C++ programmers that need speed can keep pretending 
exceptions don't exist, and if you don't need speed, why are you 
using C++? :-). Thus status quo persists and nothing interesting 
happens.


D has made C/C++ compatibility a goal... so nothing is going to 
happen with D either...


In most programs the possible call trees at a given point are 
quite limited, like a regular expression, so with whole program 
optimization you only need to special case catch blocks where the 
program may stop unwinding. I.e. you could detect which of the 
possible call trees you are in and unwind multiple stack frames 
from the same code location. If only a few functions can call 
you, you most certainly don't need to look up anything, right? If 
the compiler is allowed to move beyond the peephole separate 
compilation viewpoint...


Re: Plan for Exceptions and @nogc?

2015-02-18 Thread deadalnix via Digitalmars-d

On Wednesday, 18 February 2015 at 20:25:07 UTC, Dicebot wrote:
Right now I don't care for full memory safety or type safety of 
any proposed solution. I will be glad to have any that actually 
works - and I have not heard of any idea that allows to do that 
without language changes. Your push for owned is also hardly 
relevant because exceptions are good examples of data with 
shared / non-determenistic ownership and thus won't benefit 
from it.


I think it make sense to require that something thrown to be 
owned. That means ownership can be transferred from one thread to 
the other. That also mean that the compiler can free the 
exception when it goes out of scope, which is what is wanted for 
exception and @nogc to work together.


The invalid operation in @nogc would become promoting owned to 
Tl/shared/immutable rather than not allocating at all.


This has added benefit to allow for way more code to be @nogc, 
and in many cases transfers the GCness of something in the 
caller, which makes for @nogc compatible libraries that can be 
used in both @nogc and gc situation.


If we are gonna add something in the language, it'd better be 
worth it.


Re: Plan for Exceptions and @nogc?

2015-02-18 Thread Dicebot via Digitalmars-d

On Wednesday, 18 February 2015 at 18:26:34 UTC, deadalnix wrote:

On Wednesday, 18 February 2015 at 14:46:30 UTC, Dicebot wrote:
From my POV best proposal from last lengthy discussion was to 
enable reference-counted non-gc-heap Exceptions. But that 
needs a language change because RefCounted!T is a struct and 
thus neither can be thrown nor can be part of Throwable class 
hierarchy.




This is not satisfactory. First there is no safe way to 
refcount right now. Second, this has all kind of implication 
for the GC to scan the heap and so on. Finally this do not 
solve the type qualifier problem.


I don't think a language change to do this pay for itself. i 
understand the appeal, as this is probably simpler to implement 
than the alternative, but that is really building technical 
debt.


Right now I don't care for full memory safety or type safety of 
any proposed solution. I will be glad to have any that actually 
works - and I have not heard of any idea that allows to do that 
without language changes. Your push for owned is also hardly 
relevant because exceptions are good examples of data with shared 
/ non-determenistic ownership and thus won't benefit from it.


Re: Plan for Exceptions and @nogc?

2015-02-18 Thread Dicebot via Digitalmars-d
On Monday, 16 February 2015 at 23:17:03 UTC, Jonathan Marler 
wrote:
Is there a proposal for how D will support throwing Exceptions 
in @nogc code in the future?  I've searched the forums and 
found different proposals that involve things like 
pre-allocated exceptions, non-gc heap allocated exceptions or 
even stack allocated exceptions.  I don't want to debate the 
details of each solution, I'd just like to know if any of these 
proposals are deemed a good idea, or if any of them are 
currently being worked on.  I personally think that using 
non-gc heap allocated exceptions in combination with the new 
scope semantics would be a great solution in many cases, but I 
don't know if there is any consensus or if this topic is just 
on the back-burner. Thanks.


From my POV best proposal from last lengthy discussion was to 
enable reference-counted non-gc-heap Exceptions. But that needs a 
language change because RefCounted!T is a struct and thus neither 
can be thrown nor can be part of Throwable class hierarchy.


Any concept that implies that exceptions an be deallocated in 
`catch` block is absolutely unacceptable because it conflicts 
with exception propagation from fibers - a very important piece 
of functionality.


Re: Plan for Exceptions and @nogc?

2015-02-17 Thread deadalnix via Digitalmars-d
On Tuesday, 17 February 2015 at 15:54:17 UTC, Andrei Alexandrescu 
wrote:

On 2/16/15 3:17 PM, Jonathan Marler wrote:
Is there a proposal for how D will support throwing Exceptions 
in @nogc

code in the future?


Nothing definite. We will get on to that right after 2.067. 
This is a good time to start discussions. -- Andrei


There are various problem with exception, and @nogc is only one 
of them.


The other big issue is that exceptions bypass the type qualifier 
system.


I want to hammer once more the owned solution.


Re: Plan for Exceptions and @nogc?

2015-02-17 Thread Chris Williams via Digitalmars-d

On Wednesday, 18 February 2015 at 00:14:55 UTC, deadalnix wrote:
On Tuesday, 17 February 2015 at 19:03:49 UTC, Chris Williams 
wrote:
Every throwable function call could be assumed to have a typed 
result (even void functions) and if, after the return, the 
caller checks the type and detects that it was an error, 
bubbles that up, then eventually you get to wherever the 
catcher is.


But so basically, the current ABI doesn't support it and 
there's no desire to change it? How do exceptions currently 
happen, if not via some official ABI declaration of how 
throwable methods interact with one another? The 
compiler/linker determines where the catcher is and inserts 
code to cut down the stack and perform a long jump all the way 
back? If so, how do scope statements work?


This kind of stunt is taxing on the fast path. It can be 
implemented as setjmp/longjmp but is more and more avoided in 
favor of libunwind based solutions for languages that have code 
running on unwinding.


libunwind based solution is slower to unwind, but is not very 
taxing in the fast path (only prevent some optimizations to be 
done like tail call).


This solution is a non starter perforamnce-wize for D.


I didn't mean it as a solution. As said, I was just looking for 
an intro to the topic, so that I (and others) could meaningfully 
contribute or at least understand the options. I'll look up 
libunwind and, if that has enough info for me to grok it, create 
a wiki page on the subject.


Re: Plan for Exceptions and @nogc?

2015-02-17 Thread deadalnix via Digitalmars-d
On Tuesday, 17 February 2015 at 19:03:49 UTC, Chris Williams 
wrote:
Every throwable function call could be assumed to have a typed 
result (even void functions) and if, after the return, the 
caller checks the type and detects that it was an error, 
bubbles that up, then eventually you get to wherever the 
catcher is.


But so basically, the current ABI doesn't support it and 
there's no desire to change it? How do exceptions currently 
happen, if not via some official ABI declaration of how 
throwable methods interact with one another? The 
compiler/linker determines where the catcher is and inserts 
code to cut down the stack and perform a long jump all the way 
back? If so, how do scope statements work?


This kind of stunt is taxing on the fast path. It can be 
implemented as setjmp/longjmp but is more and more avoided in 
favor of libunwind based solutions for languages that have code 
running on unwinding.


libunwind based solution is slower to unwind, but is not very 
taxing in the fast path (only prevent some optimizations to be 
done like tail call).


This solution is a non starter perforamnce-wize for D.


Re: Plan for Exceptions and @nogc?

2015-02-17 Thread Matthias Bentrup via Digitalmars-d

On Tuesday, 17 February 2015 at 12:41:51 UTC, Marc Schütz wrote:
On Tuesday, 17 February 2015 at 09:19:55 UTC, Tobias Pankrath 
wrote:
On Tuesday, 17 February 2015 at 07:24:43 UTC, Jonathan Marler 
wrote:


Relaxing the definition of @nogc to exclude exceptions could 
be an acceptable compromise.  However, the nature of an 
exception is that it is allocated when it is created, and 
deallocated after it is caught.  This model fits nicely with 
scope semantics.  The code catching the exception would catch 
a scoped reference which means it would be responsible for 
cleaning up the exception.  It would still be allocated on 
the heap, but it wouldn't be GC memory.  This is how I think 
exceptions should have been implemented in the first place, 
but back then the GC wasn't a big deal and scope didn't exist 
yet.


This actually puts scope on the head. It's unique / ownership 
you're looking for (if at all).


Right. But `scope` still has a place in it. It would either be 
necessary to allow throwing and catching the unique/owned types 
(instead of `Throwable`), but that would be quite a change to 
the language. Or the runtime manages the exceptions (freeing 
them as soon as they are no longer needed). In that case, the 
exceptions must not leave the `catch` blocks, which is what 
`scope` guarantees.


Maybe it is possible to have a separate ScopedThrowable exception 
class.


Those exceptions would be allocated on the stack and would be 
allowed to carry references to local/scoped data, but they live 
only for the duration of the corresponding exception handler.


The compiler should check that the exception and its payload 
don't escape the catch block, and of course the exception handler 
has to run before the stack unwinding is done.


The whole point is of course that ScopedThrowables could be 
thrown from @nogc functions.


Re: Plan for Exceptions and @nogc?

2015-02-17 Thread Andrei Alexandrescu via Digitalmars-d

On 2/16/15 3:17 PM, Jonathan Marler wrote:

Is there a proposal for how D will support throwing Exceptions in @nogc
code in the future?


Nothing definite. We will get on to that right after 2.067. This is a 
good time to start discussions. -- Andrei





Re: Plan for Exceptions and @nogc?

2015-02-17 Thread Nick Treleaven via Digitalmars-d

On 17/02/2015 07:28, weaselcat wrote:

Would RefCounted!T being @nogc help alleviate this issue?


I think Andrei once said that was a good solution for exceptions.

I think the stumbling block is that if T contains indirections, 
RefCounted calls GC.addRange on the T*, which currently violates @nogc. 
Perhaps addRange should be allowed even with @nogc, as it doesn't 
trigger collections as of itself.


Otherwise, we would need some way of controlling whether addRange should 
be called by smart pointers or not.


Re: Plan for Exceptions and @nogc?

2015-02-17 Thread Nick Treleaven via Digitalmars-d

On 17/02/2015 16:15, Nick Treleaven wrote:

Would RefCounted!T being @nogc help alleviate this issue?


I think Andrei once said that was a good solution for exceptions.


Or rather that refcounting would be appropriate for exceptions, not 
necessarily RefCounted. (The compiler can't generate code using Phobos 
symbols, only druntime).


Re: Plan for Exceptions and @nogc?

2015-02-17 Thread Tobias Pankrath via Digitalmars-d

If the unwinding is done after the exception handler is left


Cannot see how that should work.


Re: Plan for Exceptions and @nogc?

2015-02-17 Thread Tobias Pankrath via Digitalmars-d
Could someone give a description of the minutiae of why 
Exception throwing uses memory allocation as it is and why (for 
example) passing it back on the stack isn't an option?


The stack frame of the thrower is the first one to be rolled 
back. So you cannot allocate in the stack frame of the thrower, 
but a function cannot now, who (if anyone) is catching the 
exceptions it might throw. So I fear the stack is out.


Re: Plan for Exceptions and @nogc?

2015-02-17 Thread Jonathan Marler via Digitalmars-d
On Tuesday, 17 February 2015 at 18:04:53 UTC, Matthias Bentrup 
wrote:
If the unwinding is done after the exception handler is left, 
the thrower can safely reference the data directly on the stack 
and the catcher can ignore any data it doesn't need. (It may 
copy the data to safety if it is needed later, but the catcher 
knows what it needs, whereas the thrower has to always assume 
the worst case.)


That is a good idea, unfortunately this is impossible since the 
catch block needs to execute code. But this is a good thought 
process.  I thought of the same thing but then realized that it 
would be impossible to ensure that the catch block wouldn't stomp 
on that memory.  This leads to having a second stack...however, 
we already have a solution...it's called the heap :)  By the time 
you're done trying to resolve this issue you will have just 
redesigned the heap.


IMO, Allocating the exception on the non-gc heap and making the 
catch block responsible for freeing the memory is a pretty good 
solution.


Re: Plan for Exceptions and @nogc?

2015-02-17 Thread Tobias Pankrath via Digitalmars-d
On Tuesday, 17 February 2015 at 18:40:51 UTC, Matthias Bentrup 
wrote:
On Tuesday, 17 February 2015 at 18:30:24 UTC, Jonathan Marler 
wrote:
I thought of the same thing but then realized that it would be 
impossible to ensure that the catch block wouldn't stomp on 
that memory.


The catcher wouldn't stomp any more on the thrower's memory 
than a function stomps on the memory of its caller. All the 
data of the thrower is safe, because it is above the stack 
pointer. The unwinding hasn't been done at that point.


That would be a deep change in language semantics. Think 
scope(exit), scope(failure), destructors of structs.


Re: Plan for Exceptions and @nogc?

2015-02-17 Thread Matthias Bentrup via Digitalmars-d
On Tuesday, 17 February 2015 at 17:38:20 UTC, Jonathan Marler 
wrote:
The reason you can't keep the thrower's stack memory around 
for the exception handler is because the exception handler may 
need that memory.  Once the exception is thrown the stack is 
unwound to the function that has the exception handler so all 
the memory gets released. In most cases the exception handler 
probably won't mess up the memory the exception is using, but 
that can't be guaranteed.




The problem I see, is that if I program a @nogc function for 
performance reasons, I'll likely have some data in scoped memory 
that is useful for handling the exception. If the stack is 
unwound before the exception handler, the thrower has to copy it 
to non-scoped memory and the catcher has to deal with it whether 
it needs the data or not.


If the unwinding is done after the exception handler is left, the 
thrower can safely reference the data directly on the stack and 
the catcher can ignore any data it doesn't need. (It may copy the 
data to safety if it is needed later, but the catcher knows what 
it needs, whereas the thrower has to always assume the worst 
case.)


Re: Plan for Exceptions and @nogc?

2015-02-17 Thread Jonathan Marler via Digitalmars-d
On Tuesday, 17 February 2015 at 13:32:40 UTC, Matthias Bentrup 
wrote:
Maybe it is possible to have a separate ScopedThrowable 
exception class.


Those exceptions would be allocated on the stack and would be 
allowed to carry references to local/scoped data, but they live 
only for the duration of the corresponding exception handler.


The compiler should check that the exception and its payload 
don't escape the catch block, and of course the exception 
handler has to run before the stack unwinding is done.


The whole point is of course that ScopedThrowables could be 
thrown from @nogc functions.


In response to allocating an exception on the stack...It depends 
on when you allocate the exception.  If the catcher of the 
exception allocates it on the stack, then you are fine so long as 
you have a way to pass a reference to it to any children 
functions, however, if the thrower allocates it on the stack then 
the memory will be released when the exception gets thrown.  It 
may make sense in some cases for the catcher to allocate the 
exception but I don't think that would be the norm.


The reason you can't keep the thrower's stack memory around for 
the exception handler is because the exception handler may need 
that memory.  Once the exception is thrown the stack is unwound 
to the function that has the exception handler so all the memory 
gets released. In most cases the exception handler probably won't 
mess up the memory the exception is using, but that can't be 
guaranteed.


As far as preventing the exception from escaping the catch 
block...that's precisely what the scope keyword would ensure.


Exception myException;

try {
   SomethingBad();
} catch(scope Exception e)
{
myException = e; // Nope. e is a scoped variable
// Note: if you needed the exception outside this
// block then you could copy the memory to another
// location.
}





Re: Plan for Exceptions and @nogc?

2015-02-17 Thread Matthias Bentrup via Digitalmars-d
On Tuesday, 17 February 2015 at 18:30:24 UTC, Jonathan Marler 
wrote:
I thought of the same thing but then realized that it would be 
impossible to ensure that the catch block wouldn't stomp on 
that memory.


The catcher wouldn't stomp any more on the thrower's memory than 
a function stomps on the memory of its caller. All the data of 
the thrower is safe, because it is above the stack pointer. The 
unwinding hasn't been done at that point.


Re: Plan for Exceptions and @nogc?

2015-02-17 Thread Chris Williams via Digitalmars-d
On Tuesday, 17 February 2015 at 15:54:17 UTC, Andrei Alexandrescu 
wrote:

On 2/16/15 3:17 PM, Jonathan Marler wrote:
Is there a proposal for how D will support throwing Exceptions 
in @nogc

code in the future?


Nothing definite. We will get on to that right after 2.067. 
This is a good time to start discussions. -- Andrei


Could someone give a description of the minutiae of why Exception 
throwing uses memory allocation as it is and why (for example) 
passing it back on the stack isn't an option?


Re: Plan for Exceptions and @nogc?

2015-02-17 Thread Chris Williams via Digitalmars-d
On Tuesday, 17 February 2015 at 18:50:46 UTC, Tobias Pankrath 
wrote:
Could someone give a description of the minutiae of why 
Exception throwing uses memory allocation as it is and why 
(for example) passing it back on the stack isn't an option?


The stack frame of the thrower is the first one to be rolled 
back. So you cannot allocate in the stack frame of the thrower, 
but a function cannot now, who (if anyone) is catching the 
exceptions it might throw. So I fear the stack is out.


Every throwable function call could be assumed to have a typed 
result (even void functions) and if, after the return, the caller 
checks the type and detects that it was an error, bubbles that 
up, then eventually you get to wherever the catcher is.


But so basically, the current ABI doesn't support it and there's 
no desire to change it? How do exceptions currently happen, if 
not via some official ABI declaration of how throwable methods 
interact with one another? The compiler/linker determines where 
the catcher is and inserts code to cut down the stack and perform 
a long jump all the way back? If so, how do scope statements work?


Re: Plan for Exceptions and @nogc?

2015-02-17 Thread Jonathan Marler via Digitalmars-d
On Tuesday, 17 February 2015 at 18:40:51 UTC, Matthias Bentrup 
wrote:
On Tuesday, 17 February 2015 at 18:30:24 UTC, Jonathan Marler 
wrote:
I thought of the same thing but then realized that it would be 
impossible to ensure that the catch block wouldn't stomp on 
that memory.


The catcher wouldn't stomp any more on the thrower's memory 
than a function stomps on the memory of its caller. All the 
data of the thrower is safe, because it is above the stack 
pointer. The unwinding hasn't been done at that point.


That would work if you didn't have to unwind the stack but 
unfortunately you do.  The catch block exists in the context of 
the function it is written in.  That means it assumes the stack 
pointer and stack variables are all in the context of it's 
defining function.  If you executed the catch code when the stack 
wasn't unwound, then it wouldn't know where any of the variables 
were.  Does that make sense?  Think about it for a minute.  You 
proposal suggests that the catch code can be executed no matter 
how many child functions have been added to the stack.  This is 
impossible since the catch code no longer knows where all of it's 
stack variables are.  Normally it uses an offset to the stack 
pointer but now it has been changed.  That's why you have to 
unwind the stack.


I like that you thought of this idea but you have to follow 
through with the details to see whether or not it would work.  I 
immediately thought of this idea and then realized that it was 
impossible.  A variation on the idea might work, but the idea as 
it is does not.  Keep thinking about it though...if nothing else 
it will give you a better understanding of the stack.  The more 
people that are intimate with the inner workings of how these 
things work the better.


Re: Plan for Exceptions and @nogc?

2015-02-17 Thread Matthias Bentrup via Digitalmars-d
On Tuesday, 17 February 2015 at 20:48:07 UTC, Jonathan Marler 
wrote:
That would work if you didn't have to unwind the stack but 
unfortunately you do.  The catch block exists in the context of 
the function it is written in.  That means it assumes the stack 
pointer and stack variables are all in the context of it's 
defining function.  If you executed the catch code when the 
stack wasn't unwound, then it wouldn't know where any of the 
variables were.  Does that make sense?  Think about it for a 
minute.  You proposal suggests that the catch code can be 
executed no matter how many child functions have been added to 
the stack.  This is impossible since the catch code no longer 
knows where all of it's stack variables are.  Normally it uses 
an offset to the stack pointer but now it has been changed.  
That's why you have to unwind the stack.


So the catcher would have to behave like a delegate.


Re: Plan for Exceptions and @nogc?

2015-02-17 Thread Jonathan Marler via Digitalmars-d
On Tuesday, 17 February 2015 at 21:30:00 UTC, Matthias Bentrup 
wrote:
On Tuesday, 17 February 2015 at 20:48:07 UTC, Jonathan Marler 
wrote:
That would work if you didn't have to unwind the stack but 
unfortunately you do.  The catch block exists in the context 
of the function it is written in.  That means it assumes the 
stack pointer and stack variables are all in the context of 
it's defining function.  If you executed the catch code when 
the stack wasn't unwound, then it wouldn't know where any of 
the variables were.  Does that make sense?  Think about it for 
a minute.  You proposal suggests that the catch code can be 
executed no matter how many child functions have been added to 
the stack.  This is impossible since the catch code no longer 
knows where all of it's stack variables are.  Normally it uses 
an offset to the stack pointer but now it has been changed.  
That's why you have to unwind the stack.


So the catcher would have to behave like a delegate.


Sure but then you're allocating GC memory again (compounding the 
problem you're trying to solve in the first place).  The best 
solution I can think of that should work in almost every case is 
to allocate the exception on the non-GC heap, then make the 
catcher cleans up the exception.  Simple, and makes sense when 
you think about the lifetime of an exception.  This would have 
been dangerous before but with the new scope semantics D can 
ensure that the exception does not escape the catch block (and 
therefore gets cleaned up properly).


Re: Plan for Exceptions and @nogc?

2015-02-17 Thread Tobias Pankrath via Digitalmars-d
On Tuesday, 17 February 2015 at 07:24:43 UTC, Jonathan Marler 
wrote:


Relaxing the definition of @nogc to exclude exceptions could be 
an acceptable compromise.  However, the nature of an exception 
is that it is allocated when it is created, and deallocated 
after it is caught.  This model fits nicely with scope 
semantics.  The code catching the exception would catch a 
scoped reference which means it would be responsible for 
cleaning up the exception.  It would still be allocated on the 
heap, but it wouldn't be GC memory.  This is how I think 
exceptions should have been implemented in the first place, but 
back then the GC wasn't a big deal and scope didn't exist yet.


This actually puts scope on the head. It's unique / ownership 
you're looking for (if at all).


Re: Plan for Exceptions and @nogc?

2015-02-17 Thread via Digitalmars-d
On Tuesday, 17 February 2015 at 09:19:55 UTC, Tobias Pankrath 
wrote:
On Tuesday, 17 February 2015 at 07:24:43 UTC, Jonathan Marler 
wrote:


Relaxing the definition of @nogc to exclude exceptions could 
be an acceptable compromise.  However, the nature of an 
exception is that it is allocated when it is created, and 
deallocated after it is caught.  This model fits nicely with 
scope semantics.  The code catching the exception would catch 
a scoped reference which means it would be responsible for 
cleaning up the exception.  It would still be allocated on the 
heap, but it wouldn't be GC memory.  This is how I think 
exceptions should have been implemented in the first place, 
but back then the GC wasn't a big deal and scope didn't exist 
yet.


This actually puts scope on the head. It's unique / ownership 
you're looking for (if at all).


Right. But `scope` still has a place in it. It would either be 
necessary to allow throwing and catching the unique/owned types 
(instead of `Throwable`), but that would be quite a change to the 
language. Or the runtime manages the exceptions (freeing them as 
soon as they are no longer needed). In that case, the exceptions 
must not leave the `catch` blocks, which is what `scope` 
guarantees.


Re: Plan for Exceptions and @nogc?

2015-02-16 Thread Jonathan Marler via Digitalmars-d

On Tuesday, 17 February 2015 at 05:52:23 UTC, philippecp wrote:
I was wondering the same myself. I think there would be a lot 
of negative side effects to using alternate memory model other 
than GC (non-gc could introduce leaks, on stack has potential 
to be overwritten). For that reason, I think the only choices 
that make sense are that either @nogc functions are also 
nothrow, or that phobos has a set of preallocated immutable 
exceptions that can can thrown.


I personally think that @nogc should be relaxed to exclude 
allocating exceptions since there would be no gc allocation 
other than for exceptional situations. I suspect that having 
code that relies on exception for main case logic is far worse 
for performance than any gc overhead anyway and is a pattern 
everyone knows to avoid.


Relaxing the definition of @nogc to exclude exceptions could be 
an acceptable compromise.  However, the nature of an exception is 
that it is allocated when it is created, and deallocated after it 
is caught.  This model fits nicely with scope semantics.  The 
code catching the exception would catch a scoped reference 
which means it would be responsible for cleaning up the 
exception.  It would still be allocated on the heap, but it 
wouldn't be GC memory.  This is how I think exceptions should 
have been implemented in the first place, but back then the GC 
wasn't a big deal and scope didn't exist yet.


Re: Plan for Exceptions and @nogc?

2015-02-16 Thread weaselcat via Digitalmars-d
On Monday, 16 February 2015 at 23:17:03 UTC, Jonathan Marler 
wrote:
Is there a proposal for how D will support throwing Exceptions 
in @nogc code in the future?  I've searched the forums and 
found different proposals that involve things like 
pre-allocated exceptions, non-gc heap allocated exceptions or 
even stack allocated exceptions.  I don't want to debate the 
details of each solution, I'd just like to know if any of these 
proposals are deemed a good idea, or if any of them are 
currently being worked on.  I personally think that using 
non-gc heap allocated exceptions in combination with the new 
scope semantics would be a great solution in many cases, but I 
don't know if there is any consensus or if this topic is just 
on the back-burner. Thanks.


Would RefCounted!T being @nogc help alleviate this issue?


Re: Plan for Exceptions and @nogc?

2015-02-16 Thread Jonathan Marler via Digitalmars-d

On Tuesday, 17 February 2015 at 07:28:03 UTC, weaselcat wrote:

Would RefCounted!T being @nogc help alleviate this issue?


I've heard of RefCounted and I understand the concept but I've 
never used it.  I'll do some reading a some experiments. Maybe 
this will work :)


Plan for Exceptions and @nogc?

2015-02-16 Thread Jonathan Marler via Digitalmars-d
Is there a proposal for how D will support throwing Exceptions in 
@nogc code in the future?  I've searched the forums and found 
different proposals that involve things like pre-allocated 
exceptions, non-gc heap allocated exceptions or even stack 
allocated exceptions.  I don't want to debate the details of each 
solution, I'd just like to know if any of these proposals are 
deemed a good idea, or if any of them are currently being 
worked on.  I personally think that using non-gc heap allocated 
exceptions in combination with the new scope semantics would be a 
great solution in many cases, but I don't know if there is any 
consensus or if this topic is just on the back-burner. Thanks.


Re: Plan for Exceptions and @nogc?

2015-02-16 Thread philippecp via Digitalmars-d
I was wondering the same myself. I think there would be a lot of 
negative side effects to using alternate memory model other than 
GC (non-gc could introduce leaks, on stack has potential to be 
overwritten). For that reason, I think the only choices that make 
sense are that either @nogc functions are also nothrow, or that 
phobos has a set of preallocated immutable exceptions that can 
can thrown.


I personally think that @nogc should be relaxed to exclude 
allocating exceptions since there would be no gc allocation other 
than for exceptional situations. I suspect that having code that 
relies on exception for main case logic is far worse for 
performance than any gc overhead anyway and is a pattern everyone 
knows to avoid.