Le 19/03/12 20:49, Denys Duchier a écrit :
Sébastien Doeraene<[email protected]> writes:
data, aka Implementation<Foo>). Besides, solution 1 is not acceptable for
Mozart, because sometimes data must mutate, and change their type. And
sometimes the mutated type occupies more memory than the previous one. So,
following me, it does not make sense to compare our model to model 1.
I really don't understand this objection. With "tag on data", when an
object A must mutate into an object B: create B, then overwrite A with a
ref to B.
And that requires that A is bigger or equal to a Ref. It is also
impossible to do with simple C++ (virtual) objects in a standard
conforming way.
It also means that the tag for an aggregate
is repeated everywhere it is referenced.
No because only one node is allowed to point to a given Implementation<T>.
Other nodes that wish to point to that Implementation<T> have to be a Reference
to the former node.
However, well, yes, you have those extra Reference types everywhere. So in some
sense the tag for an aggregate is indeed repeated everywhere it is referenced.
Indeed, I meant that the "price" of that tag was paid at every point of
reference; whether it was paid as a ref tag or as data tag.
We always pay one word to indicate the type but we don't need three
different mechanisms (tag, secondary tag, vtable) as in the old VM.
Conceptually, the mechanism is exactly the same as the primary tags in
the old VM, we just use extra bits to store the type rather than the
low-order bits of the pointer/integer. We therefore don't expect any
increase in memory usage above the factor of two inherent in using two
words for the tag & tagged.
Since we have a lot more tags available, we will also be able to
optimize many more common cases such as e.g. tuples of unary width or
tuples with a '#' label. We can also create proper types for concepts
that had to be fused by lack of tags such as characters.
Finally, not having to rely on formally undefined behaviour is more than
a theoretical advantage. Granted, most current platforms address in
8-bits bytes and use aligned pointers so we don't really need it for
portability (but exotic platforms do exist and who knows, one may become
big). However current compilers are able to aggressively optimize based
on undefined behaviour as such code paths cannot be executed in a
standard conformant program. The compiler can optimize them away without
having to prove they are actually unused. We are already hitting such
problems in the old VM. We "solved" them by disabling some optimizations
on certain source files. This is unreliable as future compilers may not
be able to disable the analyses that are necessary for optimizations (we
disable the optimization not because it's slowing down our code but
because our code is buggy in a way that for now only this optimization
detects). Optimizations (and therefore undefined behaviour assumptions)
may also leave our control. It is already possible to have the actual
compilation done at link time, doing whole-program analysis and I
wouldn't be surprised to see it done at load time in the future.
With the new implementation, we can turn on all optimizations everywhere
and let the compiler generate much more efficient code than what it
could do before. In a sense, this ends up being a time vs. memory
trade-off. And by time I mean both execution time and, more importantly,
life of the implementation.
Cheers,
--Denys
Cheers,
Yves
_________________________________________________________________________________
mozart-hackers mailing list [email protected]
http://www.mozart-oz.org/mailman/listinfo/mozart-hackers