Hi guys,
I just wanted to stress two important points Dragan makes in his
message:
- it is fix that works for now.
- a redesign is eventually needed, as the problem is in our design and
not in the compilers
So as the fix works for now it is better than nothing. Let's go for it
and find someone who feels up to redeisgning the Const/Extension craze
(too which I unfortunately contributed quite a deal of screw up, so that
means I should not do it again...).
Thanks, Dragan.
Cheers
Christian
"Dragan Havelka" <dragan@sics.se> wrote in message
news:<an97l1$ag3$1@grizzly.ps.uni-sb.de>...
> Hi guys!
>
> Mozart and alignment
> --------------------------------
>
> I will try to explain why we have problems with a
> new versions of GCC compilers.
>
> - It has to do with three things:
>
> 1) The alignment
> 2) A casting between classes (virtual subclasses)
> 3) The objects memory layout (virtual pointer
> table...)
>
> 1) All Oz values must be 8-byte aligned, i.e. last
> three bits are zero.
>
> 2) Casting between classes (virtual subclasses)
>
> Base class: OZ_Container
> / \
> Derived classes: OZ_Extension ConstTerm
>
>
>
> OZ_Extensions don't have a tag on their own. We
> use the ConstTerm's tag to "tag" OZ_Extensions.
>
> Following functions are used to "tag" and "untag"
> OZ_Extensions.
>
> a) TaggedRef makeTaggedConst(ConstTerm * p);
> b) ConstTerm tagged2Const(t);
>
> The first function expects a ConstTerm as an
> argument. To be able to use "makeTaggedConst" we
> perform an illegal casting between classes. We
> first cast OZ_Extension to OZ_Container (which is
> perfectly ok) and then cast the result to
> ConstTerm (which is wrong but it used to work, and
> we depend on it).
>
> 3) Objects memory layout (virtual pointer table...)
> The GCC-3.x compilers now have a new scheme for
> the object memory layout. The important difference
> is that "vptr" (a pointer to virtual table) is
> placed in the first word (if a class is virtual).
>
>
> example 1
> ---------------
> class OZ_Container {
> public:
> int tag;
> ....
> };
>
> class OZ_Extension : public OZ_Container {
> public:
> int type;
> virtual void foo() {}
> ....
> };
>
> class ConstTerm : public OZ_Container {
> public:
> int b;
> ....
> };
>
> int main(){
> 1: OZ_Extension* pOze = new OZ_Extension();
> // Mozart specific operator "new" that takes
> care about alignment of
> // the object
> 2: OZ_Container* pOzc = &pOze; // PROBLEM!!!!
> (pointer arith)
> // cast to OZ_Container (the base-class)
> 3: ConstTerm* pct = (ConstTerm*) pOzc;
> // cast to derived class "ConstTerm"
> 4: TaggedRef tr = makeTaggedConst(pct); //last
> three bits are now '011'
> // we expect correct aligned address and
> perform "tagging".
> .....
> // do some operation on TaggedRef
> 5: ConstTerm* pct1 = tagged2Const(tr);
> // return right address (i.e. put last three
> bits to zero)
> // but we are now on the wrong address.
> ....crash***
> }
>
> memory layout for example 1
> ------------------------------------------
> 1: We allocate an object of type OZ_Extension on
> the proper aligned address (e.g. pOze=0xbffffac0).
> The memory layout is:
>
> 0xbffffac0: _vptr.*pOze % first comes vptr
> 0xbffffac4: tag % then attributes
> from OZ_Container
> 0xbffffac8: type % then attributes
> from OZ_Extension
> ......
>
> 2: The cast that we perform in the second row will
> adjust the pointer to point to the beginning of
> OZ_Container part
> (i.e. pOzc=pOze+4=0xbffffac4).
>
> 3: The next cast will be a noop, because the class
> ConstTerm is not virtual. (i.e. pct=0xbffffac4)
>
> 4: Here we expect a correct aligned address and
> perform "tagging" (i.e. ((int) pct)+(3)) and we
> are back on the address 0xbffffac0. Now we perform
> cast back (i.e. ConstTerm* -> OZ_Container*
> ->OZ_Extension*) and we get the wrong address
> 0xbffffabc.
>
>
>
> Solutions:
> --------------
>
> My proposal
> ------------------
> We introduce a dummy virtual function in the base
> class OZ_Container. When the base class is the
> virtual class too, then casting lead to no pointer
> arithmetic. All casts that we perform will be
> "noop". I have tried GCC-3.x, VC++, and Borland,
> and all these compilers put "vptr" on the first
> place. If "vptr" is not on the first place, the
> design is still correct. I.e. we have same code in
> the any case.
>
> The "dummy" virtual method (i.e. a method that is
> never used) does not give any penalty in
> performance as far I know. I couldn't find any
> information that shows the opposite. On the other
> hand the pointer arithmetic has a price.
>
>
> Deny's proposal
> -----------------------
> We can add multiple inheritance. OZ_Extension can
> be a subclass of yet another class that will
> fill-out the space (+4 bytes). I.e. when we cast
> OZ_Extension to OZ_Container, the address will be
> shifted by 8 bytes and the new address will be
> 8-bytes aligned too.
>
> example 2
> ---------------
>
> class Padding {
> public:
> int padd;
> };
>
> class OZ_Extension : public Padding, public
> OZ_Container {
> public:
> int type;
> virtual void foo() {}
> ....
> };
>
> memory layout for example 2
> -------------------------------------------
>
> 0xbffffac0: _vptr.*pOze % first comes vptr
> 0xbffffac4: padd % then attributes
> from Padding class
> 0xbffffac8: tag % then attributes
> from OZ_Container class
> 0xbffffacc: type % then attributes
> from OZ_Extension
>
>
> We can see from memory layout that "tag" is on
> properly aligned address and it is safe to perform
> "tagging". The penalty in this case are: pointer
> arithmetic, object initializing(Padding object).
>
>
> NOTE:
> It is important to mention that both solutions are
> just temporary fixes, that just happens to work.
> The real solution demands redesign of the model
> (i.e. how OZ_Extensions should be merged into the
> system).
>
>
>
> For those of you who are interested to look my
> version:
> http://www.sics.se/~dragan/tmp/gcc3xAndMoz/
> cvs_diff.txt (contains cvs-diff against
> mozart-1-2-0-fixes)
> dragMoz-1-2-0-fixes.tar.gz (working version).
>
> or
>
> if you have an account on Sics you can run 'cvs ...'
> The repository is "/src/labs/dsl/cvs".
>
> Example:
> cvs -d r2d2@sics.se:/src/labs/dsl/cvs get -d
> mozartGCC3x dragan/mozart-gcc3x
>
> --Dragan
>
>
> >
> > (1) could you elaborate on the problem that this trick addressed?
> > quite possibly I missed it. What particular alignment issue did
> > this fix?
>
> I hope that this is now clear for you.
>
> > (2) in my opinion, this approach is not at all ok since it forces
ALL
> > our ConstTerms to have a virtual table. I prefer to only add
> > padding where absolutely needed for alignment purposes. Note
that
> > padding should be preferred (over the virtual table trick)
> > because it doesn't need initializing.
>
> O.k. That is your opinion.
> >
> >
> >>(I.e. if a base class doesn't have virtual method(s) and the derived
> >>class has, casting between the classes will lead to pointer
> >>arithmetic. If the base class has virtual method(s) then the pointer
> >>arithmetic is a noop.)
> >
> >
> > You'll have to qualify this claim a lot more to make it true :-) The
> > C++ standard doesn't guarantee this and it's not true in the new C++
> > ABI standard in the presence of multiple inheritance (it's easy to
> > construct a counter example). I have not yet been able to puzzle
> > out the C++ ABI to understand whether that's always true with single
> > inheritance of only virtual classes. At least the C++ ABI gives us
> > some guarantee about layout which C++ itself never did... now, if
> > only I could understand what these guarantees are precisely :-)
> >
>
> I am not talking about standard, I am talking
> about present situation (VC++, Borland, GCC-3.x)
>
> >
> >>I have tested my idea and the Mozart system passes the test-suite. I
> >>have also removed some badly designed casting in libdp.
> >
> >
> > We probably fixed the same casting bits. does your version actually
> > work for DP? did you have to make changes?
> >
>
> Yes.
>
>
> >
> >>4. mozart-1-2-0-fixes with Deny's modifications
> >
> >
> > There must be an error here, because I branched off the devel trunk,
> > not the release branch. What about you?
> >
>
> No errors! You have introduced tagging class
> already in mozart-1-2-0-fixes. It cannot pass
> complete test-suite but you can run benchmarks on it.
> -
> Please send submissions to hackers@mozart-oz.org
> and administriva mail to hackers-request@mozart-oz.org.
> The Mozart Oz web site is at http://www.mozart-oz.org/.
-
Please send submissions to hackers@mozart-oz.org
and administriva mail to hackers-request@mozart-oz.org.
The Mozart Oz web site is at http://www.mozart-oz.org/.