[squeak-dev] Re: [Vm-dev] Better VM <-> plugin API

Igor Stasenko siguctua at gmail.com
Sat Nov 22 07:14:57 UTC 2008


2008/11/22 Andreas Raab <andreas.raab at gmx.de>:
> Igor Stasenko wrote:
>>
>> The main reason why to use the flat namespace is to allow sharing
>> state identified by name between modules without exact knowledge where
>> this state comes from. This, of course implies some contracts about
>> meaning of symbols , e.g. "bitblt" is a function pointer which takes N
>> arguments and so on (but hey, you implying the same contract anyways,
>> when calling  ioLoadFunctionFrom("ioBitBlt", "BitBltPlugin") - just
>> with one exception, that you have to explicitly specify the source
>> module where it comes from).
>
> Well, what's interesting about this is that it becomes much more of an issue
> if this mechanism is widely used to share function pointers. Right now, 99%
> of the entry points into plugins are primitives which use the Smalltalk
> stack and do their own argument checking. There is only a tiny number of
> functions that is used directly but once you start widening that interface
> it probably becomes more of an issue. Just something to consider.
>

Of course you right. What i proposed is simplest possible enhancement.
A more secure design can be employed, if there such need.
But there always a risk of abuse regardless how much obstacles you put
- its C with direct memory access after all :)
All you need to do to be in safe is to use correct function
prototypes. But same applies to functions which you importing from
dynamic library.

>> One case, as you pointed out, is when you having multiple versions of
>> same plugin and want to swap them on the fly.
>
> Yeah, but that use case is the least convincing to me. We can do pretty much
> what you describe below (with the minor variation that it has to be an
> external plugin) and generally, the replacement of plugins has historically
> not played much of a role. For all practical intents and purposes it seems
> safer to subclass/switch the primitives in the image instead of replacing
> the plugin.
>
>> Another case, is when you want to overlook some activity by installing
>> a proxy which will log all calls to some functions.
>
> Yes, I could see doing that for debugging/auditing/tracing/profiling
> purposes. That's definitely a more interesting use case.
>
>> Third case:
>>
>> Smalltalk unloadModule: 'UnwantedStuff'.
>>
>> if there another hideous plugin (or VM) which using
>> ioLoadFunctionFrom(), it would be very hard to prevent from loading it
>> again :)
>
> I don't get this use case. Can you elaborate?
>
It comes from implementation of ioLoadFunctionFrom() - it there is no
module loaded , it tries to load it first.

>> Another one, as variant of first case (OldBlt/NewBlt), suppose you
>> have module 'fooBar' which using functionality of some 'defaultFoo'
>> module.
>> But as well, you have a 'highEndFoo' module, loaded as well which
>> having same interface as defaultFoo, but slightly different
>> implementation:
>>
>> Smalltalk lowerCPUUsage: bool
>>  bool ifTrue: [ HighEndFoo deactivate ]
>>  ifFalse: [ HighEndFoo reactivate ]
>>
>> Note, that here, #deactivate wont lead to unloading a module. It stays
>> in memory, ready to be used later, but simply rerouting things back to
>> 'defaultFoo'.
>
> Again, I find this particular use case not very convincing. In a situation
> like the above I would prefer having two classes in the image referring to
> the plugins explicitly and have my code use whichever it finds appropriate -
> because in this case you can run both the low-end as well as the high-end
> side-by-side and code won't stomp on each other by one deciding it wants to
> use the low-end and the other one deciding to use the high-end version.
>
>> I'm not saying that there's much pressing need in such use cases. But
>> these 3 functions will give us more flexibility , security and
>> modularity.
>
> How so? More flexibility, yes probably. More security? Most definitely not -
> plugins run at a trusted level already so an evil plugin can do bad things
> and nothing of what you're describing will prevent that.
> Modularity I'd say
> is arguable; but given how badly Smalltalk fares with a flat global
> namespace I'd say that you'll be hard pressed to explain how using a single
> flat namespace is an improvement over a per-plugin namespace ;-)
>

By more security, i meant a little feature, that since getting atom
value is inexpensive operation, you can
load value identified by atom and check for non-null value each time
before calling function.
Old scheme, needs to check for non-null as well, but in addition you
need to be careful to clean out this pointer when you get notification
that module, from where you taken this pointer is unloaded.

I'm not sure what you mean by per-plugin namespace.
And how much difference in namespaces between this:
 bitblt = ioLoadFunctionFrom("ioBitBlt", "BitBltPlugin")
and this:
   atom = makeAtom("BitBltPlugin.ioBitBlt");
   bitBlt = getAtomValue(atom);

The difference that first binds symbol at compile/link time, while
second - at run time.


As for modularity, let me illustrate what i meant.
There are many primitives in VM, which look like:

primitiveFoo: x with: y

^ self cCode: 'ioFoo(x,y)'.

Obviously, when you generate this code using VMMaker, it wont compile
unless you having ioFoo() function implemented somewhere.
And you have a little choice where to put this implementation - in one
of internal plugins or in platform-specific part of VM.

Now, lets consider, if i refactor this code to use atoms (i skipping
details like declarations etc) :

primitiveFoo: x with: y

ioFoo := getAtomValue: AtomIoFoo.
ioFoo notNil ifTrue: [ ^ self cCode: 'ioFoo(x,y)' ].
^ self primitiveFail.

1. the code will compile regardless i declared a function or not.
2. i'm free in choice where to put the implementation of this
function, or even build VM initially w/o this function.
3. across different platforms, one can use same VMMaker to generate
sources , and it will always compile & link.

doesn't it look like more modular?

Now, take a look at a sqWin32Stubs.c - how it would look if we would
use shared namespace? It would look as zero length file.
Because all we have to do in platform code is just initialize pointers:

pointers = {
  "ioFoo" , ioFoo
#ifdef NO_SOME_STUFF
  "ioBar" , ioBar
#endif
 ...
};

in this way, if i don't want some stuff , i can simply comment out a
line in this table and let code rot in sources :)

I'm currently trying to make a HostWindowsPlugin and want to put all
windowing and i/o stuff in it from VM platform sources.
It would be much a cut'n'paste experience to me, if all callouts in VM
would use atoms - because then i don't need to touch headers & sources
and many different places to make compiler content. Because there
would be no need in exporting function in C-like manner.

And lastly, remember InterpreterProxy thing? Each time you want to
introduce new functionality , you have to extend the structure and
increase version number. But what is it? Its just a list of pointers!
Isn't it would be simpler for plugin to just lookup a function by its
name - and use it if such function exists. Its pretty much same as
dynamic linking, just s/dlsym/getAtomValue/ and don't let your code be
constrained by compiler/linker anymore :)

>> To be fair , i'd make all plugins to export only single function, like
>> setInterpreter(), which then tells VM what things it wants to expose.
>> Currently, all plugins exposing functions and primitives in static
>> manner - and have no control at run time what to expose or not.
>> But that's another story :)
>
> Well, actually it's intrinsically related. Part of that story is that
> plugins use dlopen/dlsym for the lookup from an external plugin. It's
> because of that that the exports have to be static. So in order to make this
> dynamic you would have to have a single entry exporting it.
>

Actually the idea to use it came to my mind after reading this:
http://tronche.com/gui/x/icccm/sec-1.html#s-1 .
They calling it inter-client communications :)
As well, as hated SystemDictionary does pretty same thing :)

> Cheers,
>  - Andreas
>

-- 
Best regards,
Igor Stasenko AKA sig.



More information about the Squeak-dev mailing list