www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Looking for details of how interface method tables are implemented in

reply Dibyendu Majumdar <d.majumdar gmail.com> writes:
Hi

I am looking for details of how interface method dispatch works 
in D.
I would be grateful for any documentation of code references I 
can lookup.

In particular, I wanted to understand how similar / different the 
implementation is compared to Java.

Regards
Dibyendu
Jun 17 2023
next sibling parent user456 <user456 123.de> writes:
On Saturday, 17 June 2023 at 12:34:41 UTC, Dibyendu Majumdar 
wrote:
 Hi

 I am looking for details of how interface method dispatch works 
 in D.
 I would be grateful for any documentation of code references I 
 can lookup.

 In particular, I wanted to understand how similar / different 
 the implementation is compared to Java.

 Regards
 Dibyendu
That is specified [here](https://dlang.org/spec/abi.html#interfaces). So you have additional dereference to access the vtbl of an interface (vs class vtbl). Then an address is read in this table, cast to a function type, then called like a standard virtual call.
Jun 17 2023
prev sibling parent reply FeepingCreature <feepingcreature gmail.com> writes:
On Saturday, 17 June 2023 at 12:34:41 UTC, Dibyendu Majumdar 
wrote:
 Hi

 I am looking for details of how interface method dispatch works 
 in D.
 I would be grateful for any documentation of code references I 
 can lookup.

 In particular, I wanted to understand how similar / different 
 the implementation is compared to Java.

 Regards
 Dibyendu
Note: While writing this answer, I found the actual specified answer in the D ABI docs: https://dlang.org/spec/abi.html#classes I still think this explanation is good though. ---- I don't know for sure, but I think pretty much every single-inheritance with interface implementation in a C-like language works like this: You have a class C. C has a vtable of dynamic methods: ``` C { C_VTable* __vtable; classdata goes here } C_VTable { void function(void*) method1; void function(void*) method2; void function(void*) method3; } ``` You have a class D that inherits from C. It starts with a pointer to a D_VTable, that looks like this: ``` D_VTable { // all methods that D overrides are replaced in the C part C_VTable parent; // methods that only appear in D go here void function(void*) method4; } ``` It has to be like this, so that you can take a pointer to D and implicitly treat it as a pointer to C. --- Now what about interfaces? They're a bit complicated. Obviously an interface pointer cannot be the same pointer as the class pointer of the class that implements it. Because the interface methods would have to be at a fixed offset from the start of the vtable, and then they could collide with methods added by the class. So an interface reference is an *additional vtable pointer* in the object, that points at a dedicated interface vtable. That vtable usually also has the offset from the vtable pointer to the start of the object, because we need that to get the object reference back so we can actually call methods with it. ``` C : I { C_VTable* __vtable; C data goes here. // I i = c; results in a pointer *to this field.* I_VTable* __i_vtable; } I_VTable { size_t i_to_c_offset = -20; // or whatever void function(void*) i_method_1; void function(void*) i_method_2; void function(void*) i_method_3; } ``` Anyway, how does all that compare to Java? No clue! Sorry. I can only assume it's pretty similar, because this is really is the "unambiguously sensible" way to do it.
Jun 17 2023
parent reply Dibyendu Majumdar <d.majumdar gmail.com> writes:
On Saturday, 17 June 2023 at 17:16:16 UTC, FeepingCreature wrote:
 I am looking for details of how interface method dispatch 
 works in D.
 Note: While writing this answer, I found the actual specified 
 answer in the D ABI docs: 
 https://dlang.org/spec/abi.html#classes

 Anyway, how does all that compare to Java? No clue! Sorry. I 
 can only assume it's pretty similar, because this is really is 
 the "unambiguously sensible" way to do it.
It seems closer to C++ design, as Java does not adjust an object pointer when casting to an interface or subtype.
Jun 17 2023
parent reply FeepingCreature <feepingcreature gmail.com> writes:
On Saturday, 17 June 2023 at 20:29:35 UTC, Dibyendu Majumdar 
wrote:
 On Saturday, 17 June 2023 at 17:16:16 UTC, FeepingCreature 
 wrote:
 I am looking for details of how interface method dispatch 
 works in D.
 Note: While writing this answer, I found the actual specified 
 answer in the D ABI docs: 
 https://dlang.org/spec/abi.html#classes

 Anyway, how does all that compare to Java? No clue! Sorry. I 
 can only assume it's pretty similar, because this is really is 
 the "unambiguously sensible" way to do it.
It seems closer to C++ design, as Java does not adjust an object pointer when casting to an interface or subtype.
Ah, GPT-4 (and then Google) points me at https://wiki.openjdk.org/display/HotSpot/InterfaceCalls (It is impossible to directly google 'java interface implementation' because the results are far, far too flooded with beginner tutorials.) To summarize, it looks like Java can do interface calls on the same reference as the object mostly by paying a lot of runtime cost to find the actual method in question. In comparison, the D approach can just call the interface method at a fixed vtable offset, as it does with class methods. Once the runtime has the interface vtable, calls proceed as in D. I think comparatively, Java can more readily commit to overhead costs for interface resolution because in inner loops it expects to find a deterministic object type and create a direct call anyways. D has to compile in one shot and be done, so it has to be fast from the start.
Jun 17 2023
parent reply Dibyendu Majumdar <d.majumdar gmail.com> writes:
Follow up question.

If a class implements 5 interfaces.

I create an object of this class.

Is it correct that the resulting object has 6 vtable pointers 
embedded, one for the class, and 5 for the interfaces?

And every object that is allocated will have this overhead?

In Java land, no vtables are embedded in the object.
Jun 23 2023
parent FeepingCreature <feepingcreature gmail.com> writes:
On Friday, 23 June 2023 at 09:53:25 UTC, Dibyendu Majumdar wrote:
 Follow up question.

 If a class implements 5 interfaces.

 I create an object of this class.

 Is it correct that the resulting object has 6 vtable pointers 
 embedded, one for the class, and 5 for the interfaces?

 And every object that is allocated will have this overhead?

 In Java land, no vtables are embedded in the object.
Yep, that's correct. Though note this only applies to interfaces that are direct parents of the class; interfaces that are parents of other interfaces don't count. However conversely you do still need space for the interface pointers of your superclass. Java is a dynamically compiled language. This allows it to take liberties that are simply unfeasible for a statically compiled language. D cannot specialize a method call for a particular class at runtime; it has to be fast on its first execution, and every successive one. So trading off space for speed makes sense here. That said, if you're creating an object with six interfaces, which you are instantiating so often that its size matters, you're almost certainly writing unidiomatic D. Keep in mind that if you write D as if it was Java, you will be setting yourself up for GC and performance pain down the road.
Jun 23 2023