D - Size of type bug in D?
- christopher diggins (18/18) Apr 09 2004 I can't get the real size of a class:
- Walter (5/19) Apr 09 2004 Right. That's because you're getting the size of a reference to a class
-
christopher diggins
(39/45)
Apr 09 2004
- Walter (6/15) Apr 10 2004 That's correct.
- christopher diggins (12/27) Apr 10 2004 Then now that I have piqued your interest, the technique is to use a dou...
- Walter (5/5) Apr 15 2004 I just don't see where the performance difference is coming from. Correc...
- christopher diggins (16/21) Apr 15 2004 When using the object directly (referring to it by its concrete type) th...
- Ben Hinkle (13/17) Apr 15 2004 [snip]
- christopher diggins (13/30) Apr 15 2004 is
- Ilya Minkov (21/26) Apr 16 2004 But then again, class A inherits from an interface I, which declares a()...
- christopher diggins (51/51) Apr 15 2004 Hi Walter,
- christopher diggins (95/101) Apr 16 2004 interface
- Walter (4/4) Apr 18 2004 It is still using pointers to functions, so I don't see where the speed ...
- christopher diggins (17/21) Apr 19 2004 I apologize, I am doing a bad job of explaining myself. I will try again...
- Walter (9/26) Apr 24 2004 up
I can't get the real size of a class: class FuBar { int m1, m2; float m3; } int main() { FuBar x = new FuBar; printf("sizeof FuBar = %d\n", FuBar.size); printf("sizeof FuBar = %d\n", FuBar.sizeof); printf("sizeof FuBar = %d\n", x.size); printf("sizeof FuBar = %d\n", x.sizeof); return 0; } All of these calls output 4 bytes. -- Christopher Diggins http://www.cdiggins.com http://www.heron-language.com
Apr 09 2004
"christopher diggins" <cdiggins users.sourceforge.net> wrote in message news:c56iq9$2pmp$1 digitaldaemon.com...I can't get the real size of a class: class FuBar { int m1, m2; float m3; } int main() { FuBar x = new FuBar; printf("sizeof FuBar = %d\n", FuBar.size); printf("sizeof FuBar = %d\n", FuBar.sizeof); printf("sizeof FuBar = %d\n", x.size); printf("sizeof FuBar = %d\n", x.sizeof); return 0; } All of these calls output 4 bytes.Right. That's because you're getting the size of a reference to a class object. To get the size of the object itself: x.classinfo.init.length
Apr 09 2004
"Walter" <walter digitalmars.com> wrote in message news:c56p1b$2lj$2 digitaldaemon.com..."christopher diggins" <cdiggins users.sourceforge.net> wrote in message news:c56iq9$2pmp$1 digitaldaemon.com...<snip>I can't get the real size of a class:Right. That's because you're getting the size of a reference to a class object. To get the size of the object itself: x.classinfo.init.lengthThank you for that Walter. So armed with that new knowledge here is a very short example program: interface IFu { void Fu(); } interface IBar { void Bar(); } class Fu : IFu { void Fu() { printf("fubar fu\n"); }; } class FuBar : IFu, IBar { void Fu() { printf("fubar fu\n"); }; void Bar() { printf("fubar bar\n"); }; } class Empty { } int main() { Empty x = new Empty; Fu y = new Fu; FuBar z = new FuBar; printf("sizeof Empty = %d\n", x.classinfo.init.length); // outputs 8 printf("sizeof Fu = %d\n", y.classinfo.init.length); // outputs 12 printf("sizeof Fubar = %d\n", z.classinfo.init.length); // outputs 16 return 0; } This supports what I had suspected, that there are extra vtable pointers introduced for each interface. If you used fat pointers (double width) for interface references you could avoid the extra space overhead. There are also potentially significant performance advantages of not using vtables to implement interfaces. Is this something which is interesting to you? Or should I let this sleeping dog lie? -- Christopher Diggins http://www.cdiggins.com http://www.heron-language.com
Apr 09 2004
"christopher diggins" <cdiggins users.sourceforge.net> wrote in message news:c57q4g$1nep$1 digitaldaemon.com...This supports what I had suspected, that there are extra vtable pointers introduced for each interface.That's correct.If you used fat pointers (double width) for interface references you could avoid the extra space overhead. There are also potentially significant performance advantages of not using vtablestoimplement interfaces.I don't see how.Is this something which is interesting to you? Or should I let this sleeping dog lie?I'm curious <g>.
Apr 10 2004
"Walter" <walter digitalmars.com> wrote in message news:c59cop$143a$1 digitaldaemon.com..."christopher diggins" <cdiggins users.sourceforge.net> wrote in message news:c57q4g$1nep$1 digitaldaemon.com...Then now that I have piqued your interest, the technique is to use a double width pointer when referring to an object by reference. One part points to the object while the other points to a function table representing the functions of the interface. I wrote a C++ language extension to demonstrate the technique and have made it freely available at http://www.heron-language.com/heronfront.html . Let me know if you have any questions. Christopher Diggins http://www.cdiggins.com http://www.heron-language.comThis supports what I had suspected, that there are extra vtable pointers introduced for each interface.That's correct.If you used fat pointers (double width) for interface references you could avoid the extra space overhead. There are also potentially significant performance advantages of not using vtablestoimplement interfaces.I don't see how.Is this something which is interesting to you? Or should I let this sleeping dog lie?I'm curious <g>.
Apr 10 2004
I just don't see where the performance difference is coming from. Correct me if I'm wrong, but Heron moves the vptr from the class object to the class reference. How does that make it faster? Consider also that in D, a reference to an interface is really just a pointer to a vptr.
Apr 15 2004
When using the object directly (referring to it by its concrete type) the vtable is not needed because the functions aren't virtual. Also when referring to an object by the interface once the first call to the object is dispatched using a virtual table, calls within that function to other members of the interface shouldn't be dispatched using the vtable. Doing so would be inefficient and wrong. Am I making sense? Btw: I am working on a significantly simplified version of HeronFront that integrates smoother with standard C++ and requires less use of a pre-processor. I will announce it on this newsgroup when it is available. -- Christopher Diggins http://www.cdiggins.com http://www.heron-language.com "Walter" <walter digitalmars.com> wrote in message news:c5mhta$12t$1 digitaldaemon.com...I just don't see where the performance difference is coming from. Correctmeif I'm wrong, but Heron moves the vptr from the class object to the class reference. How does that make it faster? Consider also that in D, a reference to an interface is really just a pointer to a vptr.
Apr 15 2004
[snip]Also when referring to an object by the interface once the first call to the object is dispatched using a virtual table, calls within that function to other members of the interface shouldn't be dispatched using the vtable.[snip] Hmm. Does Heron allow a subclass to call a superclass implementation? If so then how are the function calls in the superclass made? If they are direct then they would not dispatch to the subclass methods, which seems like a bug. The only way out of this problem that I can see is that each method has two implementations: one with vtable dispatching to be used when called by the syntax super.foo() and another with direct function calls to be used elsewhere. Methods that aren't overridden get the dispatching version. Am I understanding this correctly? It seems like any C++ or D compiler could make such a time/space tradeoff during code generation - much like inlining functions is a time/space tradeoff.
Apr 15 2004
"Ben Hinkle" <bhinkle4 juno.com> wrote in message news:beiu7052nddt3gomhqbno7coqnphk7trma 4ax.com...[snip]isAlso when referring to an object by the interface once the first call to the objectI wasn't discussing Heron. Heron doesn't allow class inheritance.dispatched using a virtual table, calls within that function to other members of the interface shouldn't be dispatched using the vtable.[snip] Hmm. Does Heron allow a subclass to call a superclass implementation?If so then how are the function calls in the superclass made? If they are direct then they would not dispatch to the subclass methods, which seems like a bug. The only way out of this problem that I can see is that each method has two implementations: one with vtable dispatching to be used when called by the syntax super.foo() and another with direct function calls to be used elsewhere. Methods that aren't overridden get the dispatching version. Am I understanding this correctly? It seems like any C++ or D compiler could make such a time/space tradeoff during code generation - much like inlining functions is a time/space tradeoff.I think you got off track somewhere. The issue is that interfaces implemented as ABC's are inherently less efficient (because of the wrognful and unnecessary virtualization of functions) than when implemented alternatively such as demonstrated by the HeronFront project at http://www.heron-language.com/heronfront.html . -- Christopher Diggins http://www.cdiggins.com http://www.heron-language.com
Apr 15 2004
christopher diggins schrieb:I think you got off track somewhere. The issue is that interfaces implemented as ABC's are inherently less efficient (because of the wrognful and unnecessary virtualization of functions) than when implemented alternatively such as demonstrated by the HeronFront project at http://www.heron-language.com/heronfront.html .But then again, class A inherits from an interface I, which declares a() and b(). Class B inherits from a class A and implements the interface. Class B overrides an implementation of one of the functions a() from an interface I, but leaves b() untouched. If the b() calls a() in B, the class behaves uncoherently. This is not uncommon in C++, so in D principal decision was met to make everything virtual in classes. There are a few technical solutions to that - either such calls have to be dispatched virtually, or they can be made direct, but then each function has to be generated anew for each descendant class even if it was not overriden. These 2 make sense in different situations. The first is good for development, and for large modular systems which makes it "linkable". The second was implemented in Sather compiler, and is good for whole-program compilation - it allows to use agressive strategies to eiminate all unused code as well as agressive inlining. D can princpally support both startegies - and when the popularity of D reaches a certain point, i'm sure agressive whole-program compilers will appear. Currently, it's non-agressive C++-like only, and that for a reason. Nontheless, even in such cases D can principally cut it better than C++. -eye
Apr 16 2004
Hi Walter, Here is a sample implementation of a struct FuBar implementing an interface InterfaceFuBar which contains two functions: void Fu() and void Bar(), I'll let you do your own poking and prodding at the example and I welcome any feedback on the code itself as I am somewhat rusty at C++. Let me know if you require commenting of the code etc. #include <iostream> template<typename SELF> struct ITABLE_InterfaceFuBar { void(SELF::*Fu)(); void(SELF::*Bar)(); }; struct InterfaceFuBar { struct DUMMY_InterfaceFuBar { void Fu() { }; void Bar() { }; }; struct DUMMY_ITABLE_InterfaceFuBar : public ITABLE_InterfaceFuBar<DUMMY_InterfaceFuBar> { }; DUMMY_InterfaceFuBar* mpObject; DUMMY_ITABLE_InterfaceFuBar* mpTable; InterfaceFuBar(void* pObject = NULL, void* pTable = NULL) { mpObject = (DUMMY_InterfaceFuBar*)pObject; mpTable = (DUMMY_ITABLE_InterfaceFuBar*)pTable; }; void Fu() { (mpObject->*(mpTable->Fu))(); }; void Bar() { (mpObject->*(mpTable->Bar))(); }; }; template<typename I, typename M> struct Implementor { operator I() { return I(NULL, NULL); }; }; template<typename M> struct Implementor<InterfaceFuBar, M> { operator InterfaceFuBar() { static ITABLE_InterfaceFuBar<M> tmp = { M::Fu, M::Bar }; return InterfaceFuBar(this, (void*)&tmp); }; }; struct FuBar : public Implementor<InterfaceFuBar, FuBar> { void Fu() { std::cout << "fu" << std::endl; }; void Bar() { std::cout << "bar" << std::endl; }; }; int main() { FuBar f; InterfaceFuBar i = f; i.Fu(); std::cin.get(); return 0; } -- Christopher Diggins http://www.cdiggins.com http://www.heron-language.com
Apr 15 2004
"christopher diggins" <cdiggins users.sourceforge.net> wrote in message news:c5nk6s$1ljs$1 digitaldaemon.com...Hi Walter, Here is a sample implementation of a struct FuBar implementing aninterfaceInterfaceFuBar which contains two functions: void Fu() and void Bar(),I'lllet you do your own poking and prodding at the example and I welcome any feedback on the code itself as I am somewhat rusty at C++. Let me know if you require commenting of the code etc.So I improved on the version by removing the requirement of inheritance required on the implementing class. Just to reiterate what the heck is going on here, this is an example high performance implementation of interfaces (as they are defined in the Java specification anyway, see: http://java.sun.com/docs/books/vmspec/2nd-edition/html/Instructions2.doc6. tml#invokeinterface ) #include<iostream> using namespace std; int naff = 0; struct IFuBar { // member struct for typecasting object struct DUMMY_IFuBar { void Fu() { }; void Bar() { }; }; // ITable type for this interface template<typename SELF> struct ITABLE_IFuBar { void(SELF::*Fu)(); void(SELF::*Bar)(); }; // member struct for typecasting ITable struct DUMMY_ITABLE_IFuBar : public ITABLE_IFuBar<DUMMY_IFuBar> { // empty }; // member fields DUMMY_IFuBar* mpObject; DUMMY_ITABLE_IFuBar* mpTable; // member functions // default ctor IFuBar() { Assign(NULL, NULL); } // assignment ctor template<typename T> IFuBar(T& o) { Assign(&o, GetStaticITable<T>()); } // copy ctor template<> IFuBar(IFuBar& i) { Assign(i.mpObject, i.mpTable); } // assignment from an arbitrary object that implements the interface functiosn template<typename T> IFuBar& operator=(T& o) { Assign(&o, GetStaticITable<T>()); return *this; } // copy assignment template<> IFuBar& operator=(IFuBar& o) { Assign(o.mpObject, o.mpTable); return *this; } // assignment implementation void Assign(void* pObject, void* pTable) { mpObject = (DUMMY_IFuBar*)pObject; mpTable = (DUMMY_ITABLE_IFuBar*)pTable;; } // create static ITable for given object type template<typename T> ITABLE_IFuBar<T>* GetStaticITable() { static ITABLE_IFuBar<T> itable = { T::Fu, T::Bar }; return &itable; } // interface functions void Fu() { (mpObject->*(mpTable->Fu))(); } void Bar() { (mpObject->*(mpTable->Bar))(); } }; struct FuBar { void Fu() { naff = 0; }; void Bar() { naff = 1; }; }; struct BarFu { void Fu() { naff = 2; }; void Bar() { naff = 3; }; }; int main() { FuBar f; BarFu b; IFuBar x; x = f; x.Fu(); cout << naff << endl; x.Bar(); cout << naff << endl; IFuBar y = b; x = y; // this line is crucial, it demonstrate that IFuBar does not need the type of the object to work x.Fu(); cout << naff << endl; x.Bar(); cout << naff << endl; cin.get(); return 0; }
Apr 16 2004
It is still using pointers to functions, so I don't see where the speed up is. BTW, D implements interface dispatch much more efficiently than Java does (it's two machine instructions), so is it possible you are comparing the speedup of Heron with Java?
Apr 18 2004
"Walter" <walter digitalmars.com> wrote in message news:c5uvgd$d6j$1 digitaldaemon.com...It is still using pointers to functions, so I don't see where the speed up is. BTW, D implements interface dispatch much more efficiently than Java does (it's two machine instructions), so is it possible you are comparing the speedup of Heron with Java?I apologize, I am doing a bad job of explaining myself. I will try again. HeronFront generates interface reference objects (in C++) which are compatable with any object that implements the set of function signatures that make up the interface. This is done without requiring the object to do anything special (like making its functions virtual). So the speed up is within the objects referenced by HeronFront interface objects, compared with objects who inherit from an ABC and make all its functions virtual. There is no significant speedup between the dynamic dispatch mechanisms themselves. I have a small page and some sample code at http://www.heron-language.com/cpp-iop-example.html . Am I making more sense? -- Christopher Diggins http://www.cdiggins.com http://www.heron-language.com
Apr 19 2004
"christopher diggins" <cdiggins users.sourceforge.net> wrote in message news:c6175v$1821$1 digitaldaemon.com..."Walter" <walter digitalmars.com> wrote in message news:c5uvgd$d6j$1 digitaldaemon.com...upIt is still using pointers to functions, so I don't see where the speedcomparingis. BTW, D implements interface dispatch much more efficiently than Java does (it's two machine instructions), so is it possible you aredothe speedup of Heron with Java?I apologize, I am doing a bad job of explaining myself. I will try again. HeronFront generates interface reference objects (in C++) which are compatable with any object that implements the set of function signatures that make up the interface. This is done without requiring the object toanything special (like making its functions virtual). So the speed up is within the objects referenced by HeronFront interface objects, comparedwithobjects who inherit from an ABC and make all its functions virtual. Thereisno significant speedup between the dynamic dispatch mechanisms themselves.Ihave a small page and some sample code at http://www.heron-language.com/cpp-iop-example.html . Am I making more sense?ok, thanks for the reference.
Apr 24 2004