Some Ideas for Dynamic Vtables in D

grauzone none at example.net
Sat Feb 14 13:36:11 PST 2009


Michel Fortin wrote:
> On 2009-02-14 14:27:51 -0500, grauzone <none at example.net> said:
> 
>> Even if the heap contained all type information, what about scope 
>> classes on the stack?
> 
> Indeed. I'm aware of this reliability problem. That's in part why I also 
> proposed to add one new level of indirection to the vtable instead, 
> although I haven't mentioned it.

I think you did. But suddenly making all virtual methods "slower" would 
have a hard time to be accepted in D.

By the way, you wrote in your blog posting:
 >Updating the vtable would need to be an atomic operation, but how to do
 >this without imposing a lock at each function call?

I'm not sure, but I think at least on x86, this is not a problem. You 
can simply exchange the pointer atomically. To prevent corruption when 
several threads update the pointer, you can either use a central lock in 
the updater library code, or you use RCU (read copy update).

> 
>> For extension methods, if would probably be better to use some kind of 
>> separate vtable for this.
> 
> But how do you find the vtable for a given object? Surely you're not 
> proposing dynamically adding new vtable fields to objects?

The extension vtable can be a pointer inside the normal vtable (just 
like ClassInfo, I think). This pointer would provide an additional 
indirection, like in your proposal. Extension methods would be slightly 
slower than virtual methods, and normal virtual methods could stay as 
fast as they are now. This solution is a bit complex/redundant, but 
nobody would complain about performance issues.

Maybe one could implement extension methods as a library. The D runtime 
only needs to provide a way to add fields to ClassInfo. Like you could 
write the following code:

---------

//return value is a handle to the extension method
int addMethod()
{
	//add an extension slot to _all_ ClassInfos
	//later, this slot is used like a vtable entry
	int extension_slot = ClassInfo.allocateExtensionSlot();
	return extension_slot;
}

//method_handle = return value of addMethod()
//in_class = class, which implements the method
//method_address = address of the method
void implementMethod(int method_handle, ClassInfo in_class,
	             void* method_address)
{
	void** p = in_class.getExtensionSlotPtr(method_handle);
	//set vtable entry
	*p = method_address;
}

//method_handle = same as above
//target = Object on which the method should be invoked
//args = arguments to the method
void callMethod(Args...)(int method_handle, Object target, Args args) {
	//read method address from vtable
	ClassInfo target_class = target.classinfo;
	void** method_address_ptr =
		target_class.getExtensionSlotPtr(method_handle);
	void* method_address = *method_address_ptr;
	//use some weird assembler code here for the actual invocation
	call_method(target, method_address, &args[0]);
}

---------

How to use this:

---------

class SomeClass {
}

void my_extension_method(SomeClass this, int some_arg)
{
	//do stuff
}

int ext = addMethod();
implementMethod(ext, SomeClass.classinfo, &my_extension_method);

Object x = new SomeClass();

// the virtual extension method my_extension_method(x, 123) is called
callMethod!(int)(ext, x, 123);

---------

Unlike calling my_extension_method() directly, this can use virtual 
dispatch.

How to implement the additional ClassInfo methods?

static ClassInfo.allocateExtensionSlot() just increments a global 
counter to reserve slot entries in all ClassInfos.

ClassInfo.getExtensionSlotPtr() accesses an array internal to the 
ClassInfo instance, using its argument as an index into the array. It 
works lazily: if the extension slot doesn't exist yet in the ClassInfo, 
it extends the slot array to make place for it.

The good thing is, that you use this for other code, that needs to 
associate additional information to a ClassInfo. Actually, I would need 
something like this in my serialization code to get the per-class 
serialization metadata (call it custom RTTI) from a plain object reference.

Not sure if all this makes sense, though.



More information about the Digitalmars-d mailing list