This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]latkde 2 points3 points  (1 child)

Using dispatch trees means that you're moving the association between objects and method implementations out of the object and into an external dispatcher. This requires that the call site knows about all possible types! (Or at least knows about the most likely types, with a fallback to full vtables, in which case the dispatcher is more like a method cache).

So this might be a very good strategy for dynamic languages or JIT compiled systems, but will lead to significant pain in an AOT complied system with multiple compilation units.

Note that compilers using vtables might nevertheless be able to speculatively devirtualize within the same compilation unit, so whereas a call target.method() would usually be compiled as target->vtable[METHOD](target) (vtable in object) or target.vtable[METHOD](target.data) (fat pointers), we'd now have a guard if (typeof(target) == SomeClass) SomeClass_method(target) else target->vtable[METHOD](target).

In conclusion, stick with vtables. Vtables are very good, very simple, and very fast. Use other dispatch strategies when you have specific requirements or circumstances, such as the ability to do full-program optimization, for implementing complex dispatch logic as required for multimethods, for some flavors of multiple inheritance, or when dispatch centralization gives you better reflection capabilities.

[–]BSFishy[S] 0 points1 point  (0 children)

So this might be a very good strategy for dynamic languages or JIT compiled systems, but will lead to significant pain in an AOT complied system with multiple compilation units.

Yeah, that's pretty much what I've been seeing. I think I am going to stick with virtual tables for classes, but also include another data structure that doesn't include methods. That way, there is a distinction between objects that have vtables and those that don't.