Disadvantages of building a compiler and library on top of a specific memory management scheme

Ola Fosheim Grøstad" <ola.fosheim.grostad+dlang at gmail.com> Ola Fosheim Grøstad" <ola.fosheim.grostad+dlang at gmail.com>
Sat Feb 8 07:33:16 PST 2014


On Saturday, 8 February 2014 at 05:43:44 UTC, logicchains wrote:
> apart from superior compile-time metaprogramming? Personally, I 
> think working to improve the garbage collector could pay off in 
> this regard; "Both Rust and D allow you to choose between using 
> a garbage collector and using referencing counting, but D's 
> garbage collector is a precise concurrent generational moving 
> compacting collector, whereas Rust's is a non-parallel 
> non-moving conservative collector that's orders of magnitude 
> slower and uses much more memory." Currently, even Go has a 
> better GC than D.

Well, I think the main problem with D is that it is not a spec 
driven language, but an implementation driven language and that 
the implementation is based on compiler backends with very 
restrictive C semantics. D tries to bolt higher level 
functionality on top of that without opening up for efficient 
implementation of such features.

For instance:

1.  You could have GC free lambdas if you require that they only 
call functions that can work with fixed-size stack frames (so you 
allocate stack frames off a thread local heap where all 
allocation units are of a fixed size (say 1k)) and that they 
avoid recursion.

2. You could avoid lots of temporary allocations and copies if 
you could control what stack frames look like, by modifying the 
parent frame.

3. You could have zero overhead exception handling if you could 
get rid of the silly backwards-compatible driven design of Dwarf:

- If you fully control code gen you can have dual return points 
with a fixed offset, so you can modify the return address on the 
stack by adding an offset before returning to indicate an error 
or just jumping. The penalty is low since predicted branches tend 
to be cheap.

- If you don't need stack frames (by not having GC) you can 
maintain only frame pointers for function bodies that contains 
try blocks. Then jump straight to them on throw:

Throw becomes:

reg0 = exception_object
JMP *(framepointer+CATCHADDR)

Catch becomes:

switch(reg0.someid){
...
default:
    framepointer = *(framepointer+NEXTPTR)
    JMP *(framepointer+CATCHADDR)
}

This would make for very efficient exception handling with no 
more setup cost than you have today for stack frames. I believe.

It isn't reasonable to require that you write a backend from 
scratch, but I think it is reasonable to have a language spec 
that does not tie you to an implementation that will never go 
beyond C. If that makes adapting existing backends slightly less 
efficient, then that should be ok. It is more important to have a 
language spec that allows future compilers to be highly efficient.

- If you want mandatory GC, ok, but then change the language spec 
to make it possible to write a powerful compiler.

- If you 100% C++ parity/compatibility, great, but then make it 
just as easy (or easier) to write C++ type code without GC. 
Basically, you would have a language that consists primarily of 
syntactic sugar + some optimizing opportunities.

- If you want better performance than C. Great! But don't limit 
the language to C-semantics in the backend.

Make a decision for where you want to go at the language 
specification level. Forget about the current compiler/runtime. 
Where do you want to go?


More information about the Digitalmars-d mailing list