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

Reply via email to