View mode: basic / threaded / horizontal-split · Log in · Help
January 31, 2007
interface ABI
I wrote a scripting system where the virtual machine relies on storing
objects in void* pointers. The problem is that D handles interfaces and
classes differently. The code below prints different addresses (8 byte
offset) when Base is an interface, but same addresses when it is a class.
So my question is, why are they different like this?

Another thing I found is that when Base is an interface, the resulting
machine code is 5 operations longer (and slower). The extra code checks if
the cast object is null and calculates the offset.

import std.stdio;

interface Base {
   void Func();
}

class Foo : Base {
   void Func() {}
}

void main( char[][] args ) {
   Foo f = new Foo();
   Base b = f;

   writefln( cast(void*)f );
   writefln( cast(void*)b );

   f.Func();
   b.Func();
}
January 31, 2007
Re: interface ABI
mpt wrote:
> I wrote a scripting system where the virtual machine relies on storing
> objects in void* pointers. The problem is that D handles interfaces and
> classes differently. The code below prints different addresses (8 byte
> offset) when Base is an interface, but same addresses when it is a class.
> So my question is, why are they different like this?
> 
> Another thing I found is that when Base is an interface, the resulting
> machine code is 5 operations longer (and slower). The extra code checks if
> the cast object is null and calculates the offset.
> 
> import std.stdio;
> 
> interface Base {
>     void Func();
> }
> 
> class Foo : Base {
>     void Func() {}
> }
> 
> void main( char[][] args ) {
>     Foo f = new Foo();
>     Base b = f;
> 
>     writefln( cast(void*)f );
>     writefln( cast(void*)b );
> 
>     f.Func();
>     b.Func();
> }

An interface is implemented by adding a second v-table pointer to the 
class. The layout of the vtable is defined by the interface and includes 
an offset to the start of the object. calling a interface method should 
look something like this

size_t* inter;	// pointer to interface
inter[indexOfMethoud](inter+inter[0], args...)

Calling a class member looks something like this

size_t* inter;	// pointer to interface
inter[indexOfMethoud](inter, args...)

<rant>

Personally I'd like to see interfaces implemented as fat pointers 
carrying the object (or context) pointer and the vtable pointer 
separately. This would result in this code:

size_t[2]* inter;	// array of 2 ptrs
inter[1][indexOfMethoud](inter[0], args...)

This would allow structs to implement interfaces without having to add a 
vtable to them (thus keeping them a POD). Also other things like 
functions would be able to implement interfaces just as you can get a 
delegate from a function, struct or class.
Top | Discussion index | About this forum | D home