October 14, 2010
Nick Sabalausky:

> Then you're wasting cycles every iteration (by doing an extra addition and maybe an extra shift or even multiplication depending on T: Ie, (cast(ubyte*)myArray.ptr) + i * T.sizeof). That was a pretty common inner-loop optimization back in my C days.

With D sometimes array-based code is faster than pointer-based. With LDC they are usually equally efficient.


> Plus, I've never once done pointer arithmetic accidentally in D, so I don't see any safety to be gained from not allowing it.

I think they are trying to design a safer language. Pointer arithmetic is well known to be error-prone. (I have never asked to remove pointer arithmetic from D).


> > - Turning x++; into statements seems harsh, but indeed it solves some problems. In practice in my D programs the ++ is often used as a statement, to avoid bugs.
> 
> I've long been of the opinion that should just be a statement. All it ever does as an expression, if anything, is obfuscate code. I've never once seen a case where it clarified anything.

In some cases it shortens the code a bit, but the price to pay for such shortening is some possible bugs.

I think/hope D will turn the sub-expression deterministic, so some expressions that contain ++ and function calls will be defined in D:

Bye,
bearophile
October 14, 2010
Denis Koroskin:

> I've heard that happens in D, too. You can still call C functions at your peril, and no people complained so far.

You have stack overflows with DMD too, but I think in a segmented stack the segments are smaller than an average D stack, so it's more probable to go past one of them (I presume segmented stacks are like a deck data structure, this means a dynamic array of pointers to fixed-sized memory blocks).

Currently the main D compiler has nearly nothing to help against stack overflows, no stack guards, no static tools to compute the max stack used by a function/program, etc. I think LDC has a bit of optional stack guards.

Bye,
bearophile
October 14, 2010
On Fri, 15 Oct 2010 03:23:00 +0400, Nick Sabalausky <a@a.a> wrote:

> "bearophile" <bearophileHUGS@lycos.com> wrote in message
> news:i97utq$d7e$1@digitalmars.com...
>>
>> - In my D programs I sometimes use pointers, but pointer arithmetic is
>> indeed uncommon.
>
> If you're actually doing systems-level or high-performance work, it can be
> essential in certain cases depending on how good the optimizer is.
>
> Loops like this are fairly typical (using 'for' instead of
> 'foreach'/'map'/etc for clarity):
>
> T[] myArray = ...;
> for(int i=0; i<max; i++)
> {
>     myArray[i] // <- do something with that
> }
>
> If the compiler isn't smart enough to turn that into this:
>
> T[] myArray = ...;
> auto ptr = myArray.ptr;
> auto end = myArray.ptr + max;
> for(auto ptr = myArray.ptr; ptr<end; ptr++)
> {
>     *myArray // <- do something with that
> }
>
> Then you're wasting cycles every iteration (by doing an extra addition and
> maybe an extra shift or even multiplication depending on T: Ie,
> (cast(ubyte*)myArray.ptr) + i * T.sizeof). That was a pretty common
> inner-loop optimization back in my C days.
>
> And keep in mind, of course, real-world examples can be much more complex
> than that, so even if the compiler can handle trivial cases like this (I
> have no idea if it can, although using 'foreach' would probably make it
> easier - in some cases), it might not work for other cases. So unless the
> optimizer was known to be that good even in complex cases, I wouldn't want
> to be without pointer arithmetic. It's not needed often, but when it is
> needed it's indispensable (and still results in much more readable/portable
> code then delving down to asm).
>
> Plus, I've never once done pointer arithmetic accidentally in D, so I don't
> see any safety to be gained from not allowing it.
>

First, compiler doing pointer arithmetics != user doing pointer arithmetic.
Second, I believe it's not about a danger or accidental pointer arithmetic usage, it's more about syntax (and ambiguities it introduces).

For example, I once suggested using pointer syntax for classes too, and provided tons of arguments for that (ranging from solving tail-const issue to solving many language inconstancies that are in D between struct/class syntax and a lot more), plus a ton of additional functionality it optionally can provide if implemented. There was only one problem with that - pointer arithmetic syntax came into the way. E.g.

Foo* foo = new Foo();  foo += 1; // is that operator overloading or pointer arithmetic?
Foo foo = new Foo();  foo += 1; // compare to current version

I still hope we deprecate pointer arithmetic and introduce another syntax for it for a next major D revision (i.e. D3)

>> - Turning x++; into statements seems harsh, but indeed it solves some
>> problems. In practice in my D programs the ++ is often used as a
>> statement, to avoid bugs.
>
> I've long been of the opinion that should just be a statement. All it ever
> does as an expression, if anything, is obfuscate code. I've never once seen
> a case where it clarified anything.
>
>> - Segmented stack: allows to avoid some stack overflows at the price of a
>> bit of delay at calling functions.
>
> Seems a bad idea to force the overhead of that, but it should definitely be
> available as an option. Contrary to what Walter and Andrei seem to think,
> 32-bit systems are still very much alive and will be for quite awhile
> longer. Especially when you remember that there are more computers out there
> than just desktops and servers. (Ex: When is a phone ever going to need
> 64-bit? Eventually maybe, but certainly not anytime soon.)
>
October 15, 2010
On Thursday, October 14, 2010 16:49:58 bearophile wrote:
> Nick Sabalausky:
> > Then you're wasting cycles every iteration (by doing an extra addition
> > and maybe an extra shift or even multiplication depending on T: Ie,
> > (cast(ubyte*)myArray.ptr) + i * T.sizeof). That was a pretty common
> > inner-loop optimization back in my C days.
> 
> With D sometimes array-based code is faster than pointer-based. With LDC they are usually equally efficient.
> 
> > Plus, I've never once done pointer arithmetic accidentally in D, so I don't see any safety to be gained from not allowing it.
> 
> I think they are trying to design a safer language. Pointer arithmetic is well known to be error-prone. (I have never asked to remove pointer arithmetic from D).

There's nothing wrong with a language not having pointer arithmetic. It is an error-prone feature (hence why it's banned in SafeD) and many languages don't need it and don't have it. However, it's hard to see how a language can claim to be a systems programming language and not allow pointer arithmetic. I really need to sit down and take a good look at Go one of these days, but the more I hear about it, the less it looks like a systems programming language. They also clearly have a _very_ different approach from D, and I'd expect that the types of people who like Go wouldn't like D and vice-versa. I still need to take a good look at one of these days though.

- Jonathan M Davis
October 15, 2010
On Fri, 15 Oct 2010 02:45:33 +0300, Denis Koroskin <2korden@gmail.com> wrote:

> I've heard that happens in D, too. You can still call C functions at your peril, and no people complained so far.

I believe D (DMD, at least) is in the exact same situation as C is as far as the stack goes. There is some code in the garbage collector to get the bounds of each thread's stack, but that's it, I think.

-- 
Best regards,
 Vladimir                            mailto:vladimir@thecybershadow.net
October 15, 2010
Vladimir Panteleev wrote:
> On Fri, 15 Oct 2010 02:45:33 +0300, Denis Koroskin <2korden@gmail.com> wrote:
> 
>> I've heard that happens in D, too. You can still call C functions at your peril, and no people complained so far.
> 
> I believe D (DMD, at least) is in the exact same situation as C is as far as the stack goes.

The point of a segmented stack is to allocate stack in small bits, meaning you'll be highly likely to run out of stack calling functions that do not check for stack overflow. The usual C method, which is followed by D, is to estimate the max stack used beforehand.
October 15, 2010
bearophile wrote:
> Nick Sabalausky:
> 
>> Then you're wasting cycles every iteration (by doing an extra addition and maybe an extra shift or even multiplication depending on T: Ie, (cast(ubyte*)myArray.ptr) + i * T.sizeof). That was a pretty common inner-loop optimization back in my C days.
> 
> With D sometimes array-based code is faster than pointer-based. With LDC they are usually equally efficient.

??? This makes no sense.

The (ptr+i*T.sizeof) is an addressing mode on the x86, and comes at ZERO cost.


>> Plus, I've never once done pointer arithmetic accidentally in D, so I don't see any safety to be gained from not allowing it.
> 
> I think they are trying to design a safer language. Pointer arithmetic is well known to be error-prone.
> (I have never asked to remove pointer arithmetic from D).

D has pointers that you cannot do arithmetic on - called references. The semantics are carefully designed so a function cannot return a reference to a local, this is so that such locals will not have to be put onto the garbage collected heap. Hence, references are usable in safe mode.

Class references are also "pointers" that cannot have arithmetic on them.
October 15, 2010
"Walter Bright" <newshound2@digitalmars.com> wrote in message news:i98frv$1dm2$1@digitalmars.com...
> bearophile wrote:
>> Nick Sabalausky:
>>
>>> Then you're wasting cycles every iteration (by doing an extra addition and maybe an extra shift or even multiplication depending on T: Ie, (cast(ubyte*)myArray.ptr) + i * T.sizeof). That was a pretty common inner-loop optimization back in my C days.
>>
>> With D sometimes array-based code is faster than pointer-based. With LDC they are usually equally efficient.
>
> ??? This makes no sense.
>
> The (ptr+i*T.sizeof) is an addressing mode on the x86, and comes at ZERO cost.
>

Guess it's been way too long since I've touched x86 asm and my memory's warped :/

OTOH, not all platforms are x86 (but maybe that's still a common thing on other architectures).


October 15, 2010
Nick Sabalausky wrote:
> Seems a bad idea to force the overhead of that, but it should definitely be available as an option. Contrary to what Walter and Andrei seem to think, 32-bit systems are still very much alive and will be for quite awhile longer. Especially when you remember that there are more computers out there than just desktops and servers. (Ex: When is a phone ever going to need 64-bit? Eventually maybe, but certainly not anytime soon.)

16 bit processors died around 15 years after the introduction of 32 bit ones, even for embedded systems. If history repeats itself, figure 32 bit ones have about 5 years to go!

As for what phones need, 15 years ago, who'd a thunk we'd be using phones today for internet browsing and playing feature movies? We were all simply enthralled by a phone that didn't have a cord attached to it and fit in your pocket.

I came up with a really good virtual memory system for 16 bit code. The only problem was, by the time I figured it out, the people that needed it had moved on to protected mode with hardware vm.

I feel D will be better off preparing for the coming 64 bit tsunami.
October 15, 2010
Nick Sabalausky wrote:
> "Walter Bright" <newshound2@digitalmars.com> wrote in message news:i98frv$1dm2$1@digitalmars.com...
>> bearophile wrote:
>>> Nick Sabalausky:
>>>
>>>> Then you're wasting cycles every iteration (by doing an extra addition and maybe an extra shift or even multiplication depending on T: Ie, (cast(ubyte*)myArray.ptr) + i * T.sizeof). That was a pretty common inner-loop optimization back in my C days.
>>> With D sometimes array-based code is faster than pointer-based. With LDC they are usually equally efficient.
>> ??? This makes no sense.
>>
>> The (ptr+i*T.sizeof) is an addressing mode on the x86, and comes at ZERO cost.
>>
> 
> Guess it's been way too long since I've touched x86 asm and my memory's warped :/
> 
> OTOH, not all platforms are x86 (but maybe that's still a common thing on other architectures).

Those hardware addressing modes are not there for the 16 bit x86, and dmd's optimizer has a lot of code to rewrite loops to avoid needing them (called loop induction variables). These rewrites speed things up on 16 bit code, but slow things down for 32 bit code, and so are disabled for 32 bit code.

Write a simple loop, try it and see.