Hello,
we have a little problem while implementing a CodA meta-object protocol. The facility we try to implement now (or first :) ) is that every instance should have the possibility to add behaviour (i.e. methods) to it, but not to the class. Our first approach, which was also advised in Jeff McAffer's papers, was to insert 'anonymous' classes, which implement these methods and change the objects class to that new foo-class. However, to retain normal behaviour, we want to override the #class method to return the real class of the object, not the inserted one. The CodA metastructure will be accessed through a #meta message. As you might have expected, our problem is now, that the compiler optimizes the #class send and therefore the code only works in the debugger. Our question is now, whether there is an easy and shareable (Monticello, etc.) way to disable these optimizations and whether this idea could work with the current VM implementation? If the VM doesn't use the #class method to bind messages to an object to the methods of its class, we think that it could be possible, but if this lookup is not built into the VM but rather into the ST system, we have to go another way... Any ideas? Maybe replacing the object which shall be extended by a method with a proxy, catch every message and do the lookup ourselves? Regards, Martin |
On Nov 13, 2007, at 11:28 , Martin Beck wrote: > Hello, > > we have a little problem while implementing a CodA meta-object > protocol. The facility we try to implement now (or first :) ) is > that every instance should have the possibility to add behaviour > (i.e. methods) to it, but not to the class. Our first approach, > which was also advised in Jeff McAffer's papers, was to insert > 'anonymous' classes, which implement these methods and change the > objects class to that new foo-class. > > However, to retain normal behaviour, we want to override the #class > method to return the real class of the object, not the inserted > one. The CodA metastructure will be accessed through a #meta message. > > As you might have expected, our problem is now, that the compiler > optimizes the #class send and therefore the code only works in the > debugger. Our question is now, whether there is an easy and > shareable (Monticello, etc.) way to disable these optimizations and > whether this idea could work with the current VM implementation? If > the VM doesn't use the #class method to bind messages to an object > to the methods of its class, we think that it could be possible, > but if this lookup is not built into the VM but rather into the ST > system, we have to go another way... Wouldn't overriding #class break more things than it solves? After all, your object's class is not what it would claim to be. Which "normal behavior" would you like to "retain"? - Bert - |
Bert Freudenberg schrieb:
> > Wouldn't overriding #class break more things than it solves? After all, > your object's class is not what it would claim to be. > > Which "normal behavior" would you like to "retain"? Infact, we don't want to override Object>>#class but the #class in our generated anonymous class. It would look like this: AnonymousClass>>#class ^self baseClass So normal system behaviour is not changed, only if you alter an instance by for example adding a method, an anonymous class in the class chain is inserted which overrides the #class method. One reason to do this, is that the CodA paper specifies this behaviour, too. Another one would be, if somewhere in the system instances are tested for their classes (which shouldn't be the case...). But it seems, that this is not possible in an easy way... Regards, Martin |
Martin Beck writes:
> Bert Freudenberg schrieb: > > > > Wouldn't overriding #class break more things than it solves? After all, > > your object's class is not what it would claim to be. > > > > Which "normal behavior" would you like to "retain"? > Infact, we don't want to override Object>>#class but the #class in our > generated anonymous class. It would look like this: > > AnonymousClass>>#class > ^self baseClass > > So normal system behaviour is not changed, only if you alter an instance > by for example adding a method, an anonymous class in the class chain is > inserted which overrides the #class method. One reason to do this, is > that the CodA paper specifies this behaviour, too. Another one would be, > if somewhere in the system instances are tested for their classes (which > shouldn't be the case...). I'd suggest disabling the bytecode that implements the class message. It doesn't do a message look-up. You could do this either by converting the bytecode to a normal send (there's several bytecodes that just do sends so this should be easy) or by modifying the compiler to generate a normal send bytecode with a selector in the literal frame. I doubt that disabling this optimisation will cause problems but could be wrong. Bryce |
Hi-- > I'd suggest disabling the bytecode that implements the class message. > It doesn't do a message look-up. You could do this either by > converting the bytecode to a normal send (there's several bytecodes > that just do sends so this should be easy) or by modifying the > compiler to generate a normal send bytecode with a selector in the > literal frame. > > I doubt that disabling this optimisation will cause problems but > could be wrong. I did this for Spoon's proxy system, and it seems to work fine. -C -- Craig Latta www.netjam.org |
Craig Latta wrote:
> > I'd suggest disabling the bytecode that implements the class message. > > It doesn't do a message look-up. You could do this either by > > converting the bytecode to a normal send (there's several bytecodes > > that just do sends so this should be easy) or by modifying the > > compiler to generate a normal send bytecode with a selector in the > > literal frame. > > > > I doubt that disabling this optimisation will cause problems but > > could be wrong. > > I did this for Spoon's proxy system, and it seems to work fine. Oh, interesting. Did you ever run the macro benchmarks to see how much of a difference that makes? I've always wondered about the speed impact in a realistic kind of setting. Cheers, - Andreas |
In reply to this post by Martin Beck-3
Hi martin
this is fun. I did that in VW and it worked like you mention (see my JOOP Message passing control in Smalltalk). I defined class to return the superclass (if I remember correctly) and meta object to return the class. Then I could get instance based control as in Coda. Now in Squeak the ideas developed in the paper could not be implemented because class was not redefinable :( Stef On 13 nov. 07, at 11:28, Martin Beck wrote: > Hello, > > we have a little problem while implementing a CodA meta-object > protocol. The facility we try to implement now (or first :) ) is > that every instance should have the possibility to add behaviour > (i.e. methods) to it, but not to the class. Our first approach, > which was also advised in Jeff McAffer's papers, was to insert > 'anonymous' classes, which implement these methods and change the > objects class to that new foo-class. > > However, to retain normal behaviour, we want to override the #class > method to return the real class of the object, not the inserted > one. The CodA metastructure will be accessed through a #meta message. > > As you might have expected, our problem is now, that the compiler > optimizes the #class send and therefore the code only works in the > debugger. Our question is now, whether there is an easy and > shareable (Monticello, etc.) way to disable these optimizations and > whether this idea could work with the current VM implementation? If > the VM doesn't use the #class method to bind messages to an object > to the methods of its class, we think that it could be possible, > but if this lookup is not built into the VM but rather into the ST > system, we have to go another way... > > Any ideas? Maybe replacing the object which shall be extended by a > method with a proxy, catch every message and do the lookup ourselves? > > Regards, > Martin > > |
In reply to this post by Martin Beck-3
Hi Martin,
even though you change the implementation of the message #class, the behavior you expect will not work because the method lookup algorithm access the class field of the object header directly. So, what you really need is a way to change that field, like a primitive (something VisualWorks and VisualAge have. I don't know about Squeak...) Alejandra De Bonnis has implemented instance behavior as part of her master's thesis, adding a new field to the object header that points to a "message reception strategy" and changing the VM's method lookup in this way: 1) If the receiver's message reception strategy IS NOT nil, send the message #value: to the message reception strategy with the original message as argument (*). 2) If the receiver's message reception strategy IS nil, and the receiver's class message reception strategy IS NOT nil, send the message #value: to the receiver's class message reception strategy with the original message as argument (**). 3) Else, execute the normal method lookup (GLC in case of Squeak). (*) The message reception strategy is a "first class object". That means that you can implement in Smalltalk the behavior an object should have when receiving a message. It also means that special care had to be taken to avoid an endless loop. Our decision was to prohibit to specify a message reception strategy for those objects that represent a message reception strategy. (**) We did this because we wanted also the possibility to change the behavior of all instances of a class at once. I don't remember the right numbers on performance, but the impact was not big at all when no special behavior was configured. About memory, a word for each object was added, not that bad... She created some specials tools to manipulate this characteristics (inspectors or browsers, I don't remember exactly) If you want, we can provide you the image, vm source code, etc. IMHO, changing the VM is the best way to implement instance behavior, no need to rely on DNU, proxies, etc. This approach reifies message reception, therefore you can do what ever you want when an object receives a message. Bye, Hernan. What we did is: 1) Add a new field to the objetct On Nov 13, 2007 7:56 AM, Martin Beck <[hidden email]> wrote: Bert Freudenberg schrieb: |
In reply to this post by Andreas.Raab
> Oh, interesting. Did you ever run the macro benchmarks to see how much > of a difference that makes? I've always wondered about the speed > impact in a realistic kind of setting. Ah, in normal use there's just an additional check to see if the class of the receiver is the proxy class (which is in the special objects array). The effect on the macro benchmarks was undetectable. When proxies are involved, the network overhead of sending remote messages swamps the slowdown caused by invoking the normal sends. So, not the test you were hoping for. :) -C -- Craig Latta improvisational musical informaticist www.netjam.org Smalltalkers do: [:it | All with: Class, (And love: it)] |
In reply to this post by ccrraaiigg
Hi Craig,
thanks for your answers. Do you or anyone else have a simple hint, where in the compiler we can turn off this optimization? It is very hard to debug the parser/compiler to find the correct place... :( Regards, Martin Craig Latta wrote: > > Hi-- > > > I'd suggest disabling the bytecode that implements the class message. > > It doesn't do a message look-up. You could do this either by > > converting the bytecode to a normal send (there's several bytecodes > > that just do sends so this should be easy) or by modifying the > > compiler to generate a normal send bytecode with a selector in the > > literal frame. > > > > I doubt that disabling this optimisation will cause problems but > > could be wrong. > > I did this for Spoon's proxy system, and it seems to work fine. > > > -C > > -- > Craig Latta > www.netjam.org > > > |
Hi Martin-- > ...where in the compiler we can turn off this optimization? It is very > hard to debug the parser/compiler to find the correct place... :( Oh, I didn't change the compiler, I changed Interpreter>>bytecodePrimClass (see below) and rebuilt the interpreter. have fun, -C *** Interpreter>>bytecodePrimClass | receiver receiverClass | receiver := self internalStackTop. receiverClass := self fetchClassOf: receiver. (receiverClass = (self splObj: ClassProxy)) ifFalse: [ self internalPop: 1 thenPush: receiverClass. ^self fetchNextBytecode]. messageSelector := self specialSelector: 23. argumentCount := 0. self normalSend -- Craig Latta www.netjam.org |
Free forum by Nabble | Edit this page |