[Vm-dev] VM handle management

Andreas Raab andreas.raab at gmx.de
Wed Mar 24 04:05:53 UTC 2010


On 3/23/2010 8:56 PM, Igor Stasenko wrote:
> A good rationalization.
> So, as i understand, a VM keeps a list of (void*, char*)
> pairs in an integer-based array.

Yes, something along these lines. I hadn't specifically thought how to 
implement it, but this would certainly work.

Cheers,
   - Andreas

> Then, for image side a handle is just an integer value - an index in that array.
> The requirement is that once handle registered, both pointers should
> remain valid,
> so you can always compare strings, to make sure that type is ok.
>
> I using a following scheme for making register/unregister to be always O(1):
> Each array entry is a
> [<any data>, nextFree ]
> pair, where nextFree field used for maintaining a free entries list.
> - if element is unused(or free) , then its nextFree value>  0 , and points to a
> nextFree element. If nextFree value = 0 , then it is last free element in array.
> - if nextFree value<  0 then this element is under use.
> Additionally, there is a variable (FirstFree), which points to the
> head of free elements list.
>
> Then, registering a new element is:
> 1. check a FirstFree value,
> 2. if its 0 , then grow an array and format new elements (by filling
> all nextFree values), updating FirstFree value.Goto 1.
> 3. if its a non-zero, then set FirstFree to a nextFree value of a
> given element, and set element's nextFree to -1, to indicate that it
> is under use.
>
> Unregistering is simple as well:
>    - record a FirstFree value into nextFree field of element to be freed
>    - set  FirstFree value to an index of element which is just freed
>
> In this way, registering a new handle, or unregistering , always takes
> O(1) time, except the cases
> when you need to grow array.
>
> On 24 March 2010 05:10, Andreas Raab<andreas.raab at gmx.de>  wrote:
>>
>> Folks -
>>
>> [Warning: Long post. Please try to stay on topic and don't get into any
>> SmartSyntaxInterpreterPlugin / FFI syntax digressions that always come up
>> with these issues. This is a practical proposal that I'd like to implement].
>>
>> For the third time this month I ran into the situation that I was writing a
>> plugin that would create an internal data structure (containing pointers
>> etc) and where I wanted to return a handle to this structure and pass that
>> back to the VM.
>>
>> Since I'm a lazy bastard, what I usually do is something like this in the
>> support code:
>>
>> int sqNewFooBar(void) {
>>   /* creates a new foobar and returns a handle */
>>   FooBar *newFoo = malloc(1, sizeof(FooBar));
>>
>>   /* return a handle, sort of */
>>   return (int) newFoo;
>> }
>>
>> void sqDeleteFooBar(int handle) {
>>   FooBar *theFoo = (FooBar*) handle;
>>   free(handle);
>> }
>>
>> I don't have to tell you how horrible this is and what all the problems with
>> the approach are - I'm sure you're all well aware of it. The question is,
>> how do we fix this?
>>
>> Here's my proposal. I say let's extend the VM with 4 new proxy functions,
>> namely:
>>
>>   /* Registers a pointer and returns a handle.
>>      The type argument ensures that the handle cannot be forged. */
>>   OOP registerHandleType(void *ptr, char *type);
>>
>>   /* Unregister a handle */
>>   void unregisterHandle(void *ptr);
>>
>>   /* Look up the pointer for a given handle/pair type */
>>   void* lookupHandleType(OOP handle, char *type);
>>
>>   /* Ditto, just based on a stack index */
>>   void* stackHandleValueType(int stackIndex, char *type);
>>
>> With these functions the support code can *always* deal with pointers, never
>> with OOPs. The glue code does the translation between OOP and pointer. As a
>> consequence the above support code becomes:
>>
>> FooBar *sqNewFooBar(void) {
>>   /* creates a new foobar and returns it */
>>   FooBar *newFoo = malloc(1, sizeof(FooBar));
>>   return newFoo;
>> }
>>
>> void sqDeleteFooBar(FooBar *theFoo) {
>>   /* deletes the FooBar */
>>   free(theFoo);
>> }
>>
>> and the glue code in the plugin becomes:
>>
>> primitiveNewFooBar
>>     "Creates a new foobar"
>>     | foobar |
>>     <var: #foobar type: 'FooBar*'>
>>     foobar := self sqNewFooBar.
>>     handle := interpreterProxy registerHandle: foobar type: 'FooBar';
>>     interpreterProxy pop: interpreterProxy methodArgumentCount+1 thenPush:
>> handle.
>>
>> primitiveDestroyFooBar
>>     "Destroys a foobar"
>>     | foobar |
>>     <var: #foobar type: 'FooBar*'>
>>     foobar := interpreterProxy lookupHandle: (interpreterProxy stackValue: 0)
>> type: 'FooBar'.
>>     "or simply:
>>       foobar = interpreterProxy stackHandleValue: 0 type: 'FooBar'
>>     "
>>     foobar ifNotNil:[
>>         interpreterProxy unregisterHandle: foobar.
>>         self sqDestroy: foobar.
>>     ].
>>     interpreterProxy pop: interpreterProxy methodArgumentCount.
>>
>> What is interesting is that handles are completely opaque structures. They
>> could be integers, byte arrays, whatever representation we choose, the only
>> requirement is that the VM has a handleTable that can look up these
>> pointers.
>>
>> The obvious advantages of such a scheme are:
>>
>> * It's safe. We don't expose a pointer but rather a handle that the VM knows
>> about and that does not expose any dangerous internals.
>>
>> * It's secure. By passing the additional "type" argument you can ensure that
>> only handles registered as that type are used. I.e., no passing a SocketPtr
>> into the FilePlugin.
>>
>> * It's simple. I've written at least three handle management implementations
>> and I'm getting sick and tired of it.
>>
>> * It allows sharing. For example, OSProcessPlugin likes to do manipulate and
>> register / deregister file handles, and can now safely look up the internal
>> structure from the handle. (there are some issues here but they are no worse
>> than what OSProcess already does)
>>
>> If you agree, I'd like to implement this scheme and rewrite SocketPlugin and
>> FilePlugin as examples for how to use such handles. They are already places
>> that expose a ton of pretty risky information and it'd be a good example for
>> how to utilize handles.
>>
>> Cheers,
>>   - Andreas
>>
>
>
>


More information about the Vm-dev mailing list