tiemann@YAHI.STANFORD.EDU (Michael Tiemann) (05/10/89)
So, for example, right now, with my combination of cfront and back end compiler, Jerry's approach, where you violate the encapsulation of an object, access its instance variables directly, and lock future derived classes into using one approach to returning "size", and force a syntax of p->size rather than p->size() -- then generates code like such: movel a2@,sp@- Where as if one takes the "Object Oriented" approach of using virtual functions to return these values, so that some future class -- a linked list maybe -- can have a virtual function that calculates "p->size()" on the fly, then the [minimum] code that gets generated is: movel a3@(4),a0 addqw #8,a0 addw a0@,a3 movel a3,sp@- movel a0@(4),a0 jbsr a0@ | | V link a6,#0 movel a6@(8),a0 movel a0@,d0 unlk a6 rts | | V movel d0,sp@- For crying out loud! If you are so concerned about performance that you would be willing to rape your code if it saved you a few cycles, how about this radical approach: write in the object oriented style, AND GET A REAL MACHINE. On a RISC machine, such as the Sparc, your code example compiles into this: ld [%i0+4],%o0 // coax vtable out of `this' // with GNU C++, this may // already be in a register ld [%o0+8],%o1 // get address of virtual function | call %o1 // start call to function | mov %i0,%o0 // put `this' in first parameter V | ret // trivial function, start return | ld [%o0+8],%o0 V mov %o0,%o3 // `push' parameter Note that this sequence of instructions takes about as long on a SparcStation1 as this one: movel a2@,sp@- on a 68020 machine costing about the same money, yet it came from using code "written in the object oriented style". Let's think about the future before we write a bunch of code which will only deserve the name "dusty deck" when it finally makes it to market. RISC machines are now cheap. Let's take advantage of their power and scalability to write code which will last longer (or at least hold up better) than our predecessors' did. Reusable code isn't reusable if it's not usable... Michael
grunwald@flute.cs.uiuc.edu (05/10/89)
furthermore, remember that other optimizations are allowed, depending on
the knowledge of the type.
E.g., if you are using an instance of the function, and not a pointer
to the function, you can inline the virtual.
There are some possible language extensions that would allow you to do
load/stores a little cheaper. Examples can be found by looking at CLU.
Not using their syntax, the basic idea would be to automatically
declare functions for variables. Given this, and knowledge about the
size of the object and the semantics, you could generate simple
loads & stores. You'd need to introduce a keyword, e.g., ``mutable''
and/or ``immutable'' to distinguish read members from read/write members.
e.g.,
class Foo {
immutable int frob;
mutable double bar;
};
Foo foo;
is a class with 2 data variables & two functions: frob is read only, bar
is writable. Users could specify ``foo -> bar(10)'' or whatever syntax
you desire.
If I subclassd Foo, and hide the definition of variable `bar' with another
variable `bar', I'd still be able to generate the code via:
load foo,a0
add #4,a0
load @a0,d0
(optimize it for you machine).
But what does all this buy you? How often do you need to return data values
without additional work? If you don't have additioanl work to do, why are
they virtual data items?
I think I'm missing the range of applicability of the feature, although
it's simple to add.
--
Dirk Grunwald
Univ. of Illinois
grunwald@flute.cs.uiuc.edu