Classes or stucts :: Newbie

Jonathan M Davis jmdavisProg at gmx.com
Sun Dec 19 18:47:30 PST 2010


On Sunday 19 December 2010 18:33:56 bearophile wrote:
> Jonathan M Davis:
> > Whereas, I would argue that it's completely unnecessary.
> 
> Recently even the Oracle Java VM allocates some class instances on the
> stack, when Escape Analysis finds it's safe to do so. And D lacks the very
> efficient GC of the JVM, so for D it's even more important to use the
> stack for some classes.
> 
> Think about the "pure" tag of D2.
> 
> D1 lacks the "pure" annotation, but an advanced D1 compiler may add some
> logic able to tell if a function is pure, and use this info for
> performance purposes. The problem here is that if you change the function
> a little your function may stop being pure and the optimization becomes
> impossible. The "pure" annotation of D2 is a contract between the
> programmer and the compiler. In the same way, even if a D compiler gains
> an automatic escape analysis like Java and a much more efficient GC, a way
> to annotate a class as scoped is useful still, because like "pure" it's a
> contract between the compiler and the programmer, it enforces that a class
> instance doesn't escape a scope (if you try to escape it, the good
> compiler in most cases gives an error. While in this case the JVM just
> doesn't allocate the object on the stack), this also means guaranteed
> performance and deallocation determinism.
> 
> Another thing to keep in account is that we aren't talking just about the
> stack, but generally about in-place allocation. So if you have a class
> instance A, one of its fields may be another class instance B, that's
> scoped. Here B is allocated on the heap, because B is contained inside A,
> that is (generally) on the heap. Yet B is allocated in-place. Having a
> single heap allocation instead of two when you create an instance A is a
> significant performance gain (and I think Java doesn't perform this
> optimization yet). A well designed type system is then able to make all
> this safe.
> 
> > The compiler can help, but it can't fix the problem any more that it can
> > guarantee that a pointer to a local variable doesn't escape once you've
> > passed it to another function. In _some_ circumstances, it can catch
> > escaping pointers and references, but in the general case, it can't.
> 
> See also: http://en.wikipedia.org/wiki/Linear_types
> Stronger and more powerful type systems are possible (D has means to break
> any type system, but the programmer does this knowing what she or he is
> doing. And there are ways similar to @safe to statically disallow the
> means you may use to break this part of the type system).
> 
> >So, putting classes on the stack kind of negates the whole point of having
> >both structs and classes in the first place.<
> 
> This is false, the definition of D class instance doesn't specify where the
> instance memory is allocated.
> 
> >In the general case when using SafeD, there D _is_ safe. scoped classes
> >are definitely not in SafeD.<
> 
> SafeD is not safe. It allows integer overflows, memory overflows, etc.
> SafeD just disallows a certain (important) kind of memory bugs. This is
> why some people have asked to call it "memory safe".

The whole point of "safe" when talking about safe in D is memory saftey. And 
scoped classes are an issue of memory safety. They are _not_ safe with regards 
to memory. If the compiler can determine that a particular class object can be 
put on the stack and optimize it that way. Fine, but it's pretty rare that it 
can do that - essentially only in cases where you don't pass it to _anything_ 
except for pure functions (including calls to member functions). And if the 
compiler can do that, then it there's no need for the programmer to use scope 
explicitly.

And no, a compiler _can't_ do pure optimizations on its own, generally-speaking, 
because that would require looking not only at the body of the function that's 
being called but at the function bodies of any functions that it calls. D is not 
designed in a way that the compiler even necessarily has _access_ to a 
function's body when compiling, and you can't generally look at a function's 
body when doing optimizations when calling that function. So, _some_ pure 
optimizations could be done, but most couldn't. This is not the case with scoped 
classes, because purity already gives you the information that you need.

> If you take a look at coding standards that specify how to write high
> integrity software (MISRA-C, SPARK, Joint Strike Fighter Air Vehicle C++
> Coding Standards, etc), you will see that they forbid ALL heap
> allocations, because stack allocations are more deterministic and more
> predictable, so they are safer. If you disallow recursion the max required
> size of the stack is even computable statically, avoiding stack overflows.
> 
> ---------------------
> 
> Nick Voronin:
> >Safety is important but you don't achieve safety by means of making unsafe
> >thing unconvenient and inefficient.<
> 
> I know that sounds a little weird, but in practice this is how some parts
> of D are designed :-) Yet, Walter has said many things that he doesn't
> like "safety by convention". So I presume there is some contradiction here
> :-)

Safety by convention means that the language and the compiler do not enforce it 
in any way. When the language is designed to include it, then it's _not_ by 
convention. So, for instance, Go doesn't use its type system to protect you from 
threads stomping on each other. Rather, the safety is done by convention - the 
programmer does it by programming in a particular way. In D, on the other hand, 
the type system enforces it. There's nothing contradictory about Walter's 
stance. He's for having safety built into the language as much as reasonably 
possible and against having it thrust upon the programmer to program in a 
particular way to avoid unsafe stuff. @safe is a prime example of this (assuming 
that's implemented correctly, which isn't the case at the moment). It causes the 
compiler to enforce that only safe operations are used rather than relying on 
the programmer not to use unsafe operations.

- Jonathan M Davis


More information about the Digitalmars-d-learn mailing list