Tracing special messages [WAS] Re: [Vm-dev] Re: normalSend, specialObjectsArray and VM

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
9 messages Options
Reply | Threaded
Open this post in threaded view
|

Tracing special messages [WAS] Re: [Vm-dev] Re: normalSend, specialObjectsArray and VM

Mariano Martinez Peck
 
Hi. So....if I want to intercept ALL message sends....going to #normalSend is not enough since I have #class, #==, Float>>#+   etc that are executed directly like bytecodes. So...my questions are now:

1) Those special selectors are those that are in "Smalltalk specialSelectors" ?  are there more?  all from there are special?

2) All those "Smalltalk specialSelectors"  have their associated bytecode primitive in Interpreter??  If true, then I should modify all bytecodePrim*  in Interpreter. I am right?   If I do that, that's all ? I am intercepting everything?

Thanks a lot in advance,

Mariano



On Sun, Oct 3, 2010 at 11:09 PM, Craig Latta <[hidden email]> wrote:


> Craig Latta has done all this work, talk to him.

    Sure, I'd be happy to discuss it.


-C

--
Craig Latta
www.netjam.org
+ 31 020 894 6247
+  1 415 287 3547




Reply | Threaded
Open this post in threaded view
|

Re: Tracing special messages [WAS] Re: [Vm-dev] Re: normalSend, specialObjectsArray and VM

Mariano Martinez Peck
 


On Tue, Oct 5, 2010 at 6:23 PM, Mariano Martinez Peck <[hidden email]> wrote:
Hi. So....if I want to intercept ALL message sends....going to #normalSend is not enough since I have #class, #==, Float>>#+   etc that are executed directly like bytecodes. So...my questions are now:

1) Those special selectors are those that are in "Smalltalk specialSelectors" ?  are there more?  all from there are special?

2) All those "Smalltalk specialSelectors"  have their associated bytecode primitive in Interpreter??  If true, then I should modify all bytecodePrim*  in Interpreter. I am right?   If I do that, that's all ? I am intercepting everything?


Sorry I need not to count those bytecodePrim* that do a "normalSend" at the end. Isn't it?
 
Thanks a lot in advance,

Mariano



On Sun, Oct 3, 2010 at 11:09 PM, Craig Latta <[hidden email]> wrote:


> Craig Latta has done all this work, talk to him.

    Sure, I'd be happy to discuss it.


-C

--
Craig Latta
www.netjam.org
+ 31 020 894 6247
+  1 415 287 3547





Reply | Threaded
Open this post in threaded view
|

Re: Tracing special messages [WAS] Re: [Vm-dev] Re: normalSend, specialObjectsArray and VM

Eliot Miranda-2
In reply to this post by Mariano Martinez Peck
 


On Tue, Oct 5, 2010 at 9:23 AM, Mariano Martinez Peck <[hidden email]> wrote:
 
Hi. So....if I want to intercept ALL message sends....going to #normalSend is not enough since I have #class, #==, Float>>#+   etc that are executed directly like bytecodes. So...my questions are now:

1) Those special selectors are those that are in "Smalltalk specialSelectors" ?  are there more?  all from there are special?

2) All those "Smalltalk specialSelectors"  have their associated bytecode primitive in Interpreter??  If true, then I should modify all bytecodePrim*  in Interpreter. I am right?   If I do that, that's all ? I am intercepting everything?

Right.  Just modify all of them to eliminate the optimized code and to revert to normalSend.  Providing you also look at the perform and method evaluation primitives I think you'll get all sends. 

There is another way.  Modify the Smalltalk compiler to to use the special selector sends.


Thanks a lot in advance,

Mariano



On Sun, Oct 3, 2010 at 11:09 PM, Craig Latta <[hidden email]> wrote:


> Craig Latta has done all this work, talk to him.

    Sure, I'd be happy to discuss it.


-C

--
Craig Latta
www.netjam.org
+ 31 020 894 6247
+  1 415 287 3547






Reply | Threaded
Open this post in threaded view
|

Re: Tracing special messages [WAS] Re: [Vm-dev] Re: normalSend, specialObjectsArray and VM

Mariano Martinez Peck
 


On Tue, Oct 5, 2010 at 7:50 PM, Eliot Miranda <[hidden email]> wrote:
 


On Tue, Oct 5, 2010 at 9:23 AM, Mariano Martinez Peck <[hidden email]> wrote:
 
Hi. So....if I want to intercept ALL message sends....going to #normalSend is not enough since I have #class, #==, Float>>#+   etc that are executed directly like bytecodes. So...my questions are now:

1) Those special selectors are those that are in "Smalltalk specialSelectors" ?  are there more?  all from there are special?

2) All those "Smalltalk specialSelectors"  have their associated bytecode primitive in Interpreter??  If true, then I should modify all bytecodePrim*  in Interpreter. I am right?   If I do that, that's all ? I am intercepting everything?

Right.  Just modify all of them to eliminate the optimized code and to revert to normalSend.  

Thanks Eliot. I didn't understand. What is the optimized code?   I checked all bytecodePrim* and the ones that DO NOT send "self normalSend" at the end, are very few. The problem is that some return before returning "self normalSend". So...I should modify all those who DO NOT call "self normalSend" at the end and those which return before.

 
Providing you also look at the perform and method evaluation primitives I think you'll get all sends. 


#primitivePerform*   and #primitiveExecuteMethod*    ???
   
There is another way.  Modify the Smalltalk compiler to to use the special selector sends.


Thanks Eliot for the idea. Can you explain me a little more (sorry, newbie here!). You mean that with the Compiler I can do that all method sends use the normal send instead of special bytecodes or primitives?

Thank you very much.

Mariano
 

Thanks a lot in advance,

Mariano



On Sun, Oct 3, 2010 at 11:09 PM, Craig Latta <[hidden email]> wrote:


> Craig Latta has done all this work, talk to him.

    Sure, I'd be happy to discuss it.


-C

--
Craig Latta
www.netjam.org
+ 31 020 894 6247
+  1 415 287 3547








Reply | Threaded
Open this post in threaded view
|

Re: Tracing special messages [WAS] Re: [Vm-dev] Re: normalSend, specialObjectsArray and VM

Eliot Miranda-2
 


On Tue, Oct 5, 2010 at 11:20 AM, Mariano Martinez Peck <[hidden email]> wrote:
 


On Tue, Oct 5, 2010 at 7:50 PM, Eliot Miranda <[hidden email]> wrote:
 


On Tue, Oct 5, 2010 at 9:23 AM, Mariano Martinez Peck <[hidden email]> wrote:
 
Hi. So....if I want to intercept ALL message sends....going to #normalSend is not enough since I have #class, #==, Float>>#+   etc that are executed directly like bytecodes. So...my questions are now:

1) Those special selectors are those that are in "Smalltalk specialSelectors" ?  are there more?  all from there are special?

2) All those "Smalltalk specialSelectors"  have their associated bytecode primitive in Interpreter??  If true, then I should modify all bytecodePrim*  in Interpreter. I am right?   If I do that, that's all ? I am intercepting everything?

Right.  Just modify all of them to eliminate the optimized code and to revert to normalSend.  

Thanks Eliot. I didn't understand. What is the optimized code?   I checked all bytecodePrim* and the ones that DO NOT send "self normalSend" at the end, are very few. The problem is that some return before returning "self normalSend". So...I should modify all those who DO NOT call "self normalSend" at the end and those which return before.

Change them all so they do a normalSend and nothing else, e.g.

bytecodePrimAdd
messageSelector := self specialSelector: 0.
argumentCount := 1.
self normalSend

Or change the part of the bytecode table that specifies the special selector primitives to read
(176 207 sendSpecialSelectorBytecode)

sendSpecialSelectorBytecode
| selectorIndex specialSelectors |
selectorIndex := (currentBytecode - 176) * 2.
specialSelectors := self splObj: SpecialSelectors.
messageSelector := self fetchPointer: selectorIndex
ofObject: specialSelectors.
argumentCount := self fetchInteger: selectorIndex + 1
ofObject: specialSelectors.
self normalSend

But most of all try and slow down and understand what is going on; then you will be able to answer your own questions.  Reading the blue book will help.
 

 
Providing you also look at the perform and method evaluation primitives I think you'll get all sends. 


#primitivePerform*   and #primitiveExecuteMethod*    ???
   
There is another way.  Modify the Smalltalk compiler to to use the special selector sends.


Thanks Eliot for the idea. Can you explain me a little more (sorry, newbie here!). You mean that with the Compiler I can do that all method sends use the normal send instead of special bytecodes or primitives?

Yes.  If you modify the compiler not to use the StdSelectors then the compiler will emit normal sends for all the special selectors.   Again I think if you slowed down and started playing ore you would discover this for yourself and in the end be more productive.  I know its hard and frustrating initially.  But my own competence comes directly from having played around in this way.

best,
Eliot


Thank you very much.

Mariano
 

Thanks a lot in advance,

Mariano



On Sun, Oct 3, 2010 at 11:09 PM, Craig Latta <[hidden email]> wrote:


> Craig Latta has done all this work, talk to him.

    Sure, I'd be happy to discuss it.


-C

--
Craig Latta
www.netjam.org
+ 31 020 894 6247
+  1 415 287 3547










Reply | Threaded
Open this post in threaded view
|

Re: Tracing special messages [WAS] Re: [Vm-dev] Re: normalSend, specialObjectsArray and VM

Mariano Martinez Peck
 


On Tue, Oct 5, 2010 at 8:48 PM, Eliot Miranda <[hidden email]> wrote:
 


On Tue, Oct 5, 2010 at 11:20 AM, Mariano Martinez Peck <[hidden email]> wrote:
 


On Tue, Oct 5, 2010 at 7:50 PM, Eliot Miranda <[hidden email]> wrote:
 


On Tue, Oct 5, 2010 at 9:23 AM, Mariano Martinez Peck <[hidden email]> wrote:
 
Hi. So....if I want to intercept ALL message sends....going to #normalSend is not enough since I have #class, #==, Float>>#+   etc that are executed directly like bytecodes. So...my questions are now:

1) Those special selectors are those that are in "Smalltalk specialSelectors" ?  are there more?  all from there are special?

2) All those "Smalltalk specialSelectors"  have their associated bytecode primitive in Interpreter??  If true, then I should modify all bytecodePrim*  in Interpreter. I am right?   If I do that, that's all ? I am intercepting everything?

Right.  Just modify all of them to eliminate the optimized code and to revert to normalSend.  

Thanks Eliot. I didn't understand. What is the optimized code?   I checked all bytecodePrim* and the ones that DO NOT send "self normalSend" at the end, are very few. The problem is that some return before returning "self normalSend". So...I should modify all those who DO NOT call "self normalSend" at the end and those which return before.

Change them all so they do a normalSend and nothing else, e.g.

bytecodePrimAdd
messageSelector := self specialSelector: 0.
argumentCount := 1.
self normalSend


Ok, but suppose I DON'T want to slow down the system.... what if I change to this for example

bytecodePrimAdd
    | rcvr arg result |
    rcvr := self internalStackValue: 1.
    arg := self internalStackValue: 0.
    (self areIntegers: rcvr and: arg)
        ifTrue: [result := (self integerValueOf: rcvr) + (self integerValueOf: arg).
                (self isIntegerValue: result) ifTrue:
                    [self internalPop: 2 thenPush: (self integerObjectOf: result).
                    self markObjectUsage: rcvr.
                    ^ self fetchNextBytecode "success"]]
        ifFalse: [successFlag := true.
                self externalizeIPandSP.
                self primitiveFloatAdd: rcvr toArg: arg.
                self internalizeIPandSP.
                successFlag ifTrue: [self markObjectUsage: rcvr. ^ self fetchNextBytecode "success"]].

    messageSelector := self specialSelector: 0.
    argumentCount := 1.
    self normalSend

Ok...I have to manually check each method, but I don't have problem.

Should that work and be almost as fast as normally?

 
Or change the part of the bytecode table that specifies the special selector primitives to read
(176 207 sendSpecialSelectorBytecode)

sendSpecialSelectorBytecode
| selectorIndex specialSelectors |
selectorIndex := (currentBytecode - 176) * 2.
specialSelectors := self splObj: SpecialSelectors.
messageSelector := self fetchPointer: selectorIndex
ofObject: specialSelectors.
argumentCount := self fetchInteger: selectorIndex + 1
ofObject: specialSelectors.
self normalSend

But most of all try and slow down and understand what is going on; then you will be able to answer your own questions.  Reading the blue book will help.
 

hehehehehe what an idea :) I didn't know I could do that. Thanks for the blue book. I read the vm chapters but several months ago. I should read it again since the first time I didn't understand very much hehehehe.
 

 
Providing you also look at the perform and method evaluation primitives I think you'll get all sends. 


#primitivePerform*   and #primitiveExecuteMethod*    ???
   
There is another way.  Modify the Smalltalk compiler to to use the special selector sends.


Thanks Eliot for the idea. Can you explain me a little more (sorry, newbie here!). You mean that with the Compiler I can do that all method sends use the normal send instead of special bytecodes or primitives?

Yes.  If you modify the compiler not to use the StdSelectors then the compiler will emit normal sends for all the special selectors.   Again I think if you slowed down and started playing ore you would discover this for yourself and in the end be more productive.  I know its hard and frustrating initially.  But my own competence comes directly from having played around in this way.


Thanks Eliot. I will consider this alternative also.

Best regards.

Mariano
 
best,
Eliot


Thank you very much.

Mariano
 

Thanks a lot in advance,

Mariano



On Sun, Oct 3, 2010 at 11:09 PM, Craig Latta <[hidden email]> wrote:


> Craig Latta has done all this work, talk to him.

    Sure, I'd be happy to discuss it.


-C

--
Craig Latta
www.netjam.org
+ 31 020 894 6247
+  1 415 287 3547












Reply | Threaded
Open this post in threaded view
|

Re: Tracing special messages [WAS] Re: [Vm-dev] Re: normalSend, specialObjectsArray and VM

Eliot Miranda-2
 


On Tue, Oct 5, 2010 at 12:00 PM, Mariano Martinez Peck <[hidden email]> wrote:
 


On Tue, Oct 5, 2010 at 8:48 PM, Eliot Miranda <[hidden email]> wrote:
 


On Tue, Oct 5, 2010 at 11:20 AM, Mariano Martinez Peck <[hidden email]> wrote:
 


On Tue, Oct 5, 2010 at 7:50 PM, Eliot Miranda <[hidden email]> wrote:
 


On Tue, Oct 5, 2010 at 9:23 AM, Mariano Martinez Peck <[hidden email]> wrote:
 
Hi. So....if I want to intercept ALL message sends....going to #normalSend is not enough since I have #class, #==, Float>>#+   etc that are executed directly like bytecodes. So...my questions are now:

1) Those special selectors are those that are in "Smalltalk specialSelectors" ?  are there more?  all from there are special?

2) All those "Smalltalk specialSelectors"  have their associated bytecode primitive in Interpreter??  If true, then I should modify all bytecodePrim*  in Interpreter. I am right?   If I do that, that's all ? I am intercepting everything?

Right.  Just modify all of them to eliminate the optimized code and to revert to normalSend.  

Thanks Eliot. I didn't understand. What is the optimized code?   I checked all bytecodePrim* and the ones that DO NOT send "self normalSend" at the end, are very few. The problem is that some return before returning "self normalSend". So...I should modify all those who DO NOT call "self normalSend" at the end and those which return before.

Change them all so they do a normalSend and nothing else, e.g.

bytecodePrimAdd
messageSelector := self specialSelector: 0.
argumentCount := 1.
self normalSend


Ok, but suppose I DON'T want to slow down the system.... what if I change to this for example

bytecodePrimAdd
    | rcvr arg result |
    rcvr := self internalStackValue: 1.
    arg := self internalStackValue: 0.
    (self areIntegers: rcvr and: arg)
        ifTrue: [result := (self integerValueOf: rcvr) + (self integerValueOf: arg).
                (self isIntegerValue: result) ifTrue:
                    [self internalPop: 2 thenPush: (self integerObjectOf: result).
                    self markObjectUsage: rcvr.
                    ^ self fetchNextBytecode "success"]]
        ifFalse: [successFlag := true.
                self externalizeIPandSP.
                self primitiveFloatAdd: rcvr toArg: arg.
                self internalizeIPandSP.
                successFlag ifTrue: [self markObjectUsage: rcvr. ^ self fetchNextBytecode "success"]].

    messageSelector := self specialSelector: 0.
    argumentCount := 1.
    self normalSend

Ok...I have to manually check each method, but I don't have problem.

Should that work and be almost as fast as normally?

But it doesn't mark the method right?  It only marks the objects.  However if you analyse the bytecodePrimFoo implementations you should be able to work out which methods are used, SmallInteger>>#+, Float>>#+ et al.

 
Or change the part of the bytecode table that specifies the special selector primitives to read
(176 207 sendSpecialSelectorBytecode)

sendSpecialSelectorBytecode
| selectorIndex specialSelectors |
selectorIndex := (currentBytecode - 176) * 2.
specialSelectors := self splObj: SpecialSelectors.
messageSelector := self fetchPointer: selectorIndex
ofObject: specialSelectors.
argumentCount := self fetchInteger: selectorIndex + 1
ofObject: specialSelectors.
self normalSend

But most of all try and slow down and understand what is going on; then you will be able to answer your own questions.  Reading the blue book will help.
 

hehehehehe what an idea :) I didn't know I could do that. Thanks for the blue book. I read the vm chapters but several months ago. I should read it again since the first time I didn't understand very much hehehehe.
 

 
Providing you also look at the perform and method evaluation primitives I think you'll get all sends. 


#primitivePerform*   and #primitiveExecuteMethod*    ???
   
There is another way.  Modify the Smalltalk compiler to to use the special selector sends.


Thanks Eliot for the idea. Can you explain me a little more (sorry, newbie here!). You mean that with the Compiler I can do that all method sends use the normal send instead of special bytecodes or primitives?

Yes.  If you modify the compiler not to use the StdSelectors then the compiler will emit normal sends for all the special selectors.   Again I think if you slowed down and started playing ore you would discover this for yourself and in the end be more productive.  I know its hard and frustrating initially.  But my own competence comes directly from having played around in this way.


Thanks Eliot. I will consider this alternative also.

Best regards.

Mariano
 
best,
Eliot


Thank you very much.

Mariano
 

Thanks a lot in advance,

Mariano



On Sun, Oct 3, 2010 at 11:09 PM, Craig Latta <[hidden email]> wrote:


> Craig Latta has done all this work, talk to him.

    Sure, I'd be happy to discuss it.


-C

--
Craig Latta
www.netjam.org
+ 31 020 894 6247
+  1 415 287 3547














Reply | Threaded
Open this post in threaded view
|

Re: Tracing special messages [WAS] Re: [Vm-dev] Re: normalSend, specialObjectsArray and VM

Mariano Martinez Peck
 


On Tue, Oct 5, 2010 at 9:04 PM, Eliot Miranda <[hidden email]> wrote:
 


On Tue, Oct 5, 2010 at 12:00 PM, Mariano Martinez Peck <[hidden email]> wrote:
 


On Tue, Oct 5, 2010 at 8:48 PM, Eliot Miranda <[hidden email]> wrote:
 


On Tue, Oct 5, 2010 at 11:20 AM, Mariano Martinez Peck <[hidden email]> wrote:
 


On Tue, Oct 5, 2010 at 7:50 PM, Eliot Miranda <[hidden email]> wrote:
 


On Tue, Oct 5, 2010 at 9:23 AM, Mariano Martinez Peck <[hidden email]> wrote:
 
Hi. So....if I want to intercept ALL message sends....going to #normalSend is not enough since I have #class, #==, Float>>#+   etc that are executed directly like bytecodes. So...my questions are now:

1) Those special selectors are those that are in "Smalltalk specialSelectors" ?  are there more?  all from there are special?

2) All those "Smalltalk specialSelectors"  have their associated bytecode primitive in Interpreter??  If true, then I should modify all bytecodePrim*  in Interpreter. I am right?   If I do that, that's all ? I am intercepting everything?

Right.  Just modify all of them to eliminate the optimized code and to revert to normalSend.  

Thanks Eliot. I didn't understand. What is the optimized code?   I checked all bytecodePrim* and the ones that DO NOT send "self normalSend" at the end, are very few. The problem is that some return before returning "self normalSend". So...I should modify all those who DO NOT call "self normalSend" at the end and those which return before.

Change them all so they do a normalSend and nothing else, e.g.

bytecodePrimAdd
messageSelector := self specialSelector: 0.
argumentCount := 1.
self normalSend


Ok, but suppose I DON'T want to slow down the system.... what if I change to this for example

bytecodePrimAdd
    | rcvr arg result |
    rcvr := self internalStackValue: 1.
    arg := self internalStackValue: 0.
    (self areIntegers: rcvr and: arg)
        ifTrue: [result := (self integerValueOf: rcvr) + (self integerValueOf: arg).
                (self isIntegerValue: result) ifTrue:
                    [self internalPop: 2 thenPush: (self integerObjectOf: result).
                    self markObjectUsage: rcvr.
                    ^ self fetchNextBytecode "success"]]
        ifFalse: [successFlag := true.
                self externalizeIPandSP.
                self primitiveFloatAdd: rcvr toArg: arg.
                self internalizeIPandSP.
                successFlag ifTrue: [self markObjectUsage: rcvr. ^ self fetchNextBytecode "success"]].

    messageSelector := self specialSelector: 0.
    argumentCount := 1.
    self normalSend

Ok...I have to manually check each method, but I don't have problem.

Should that work and be almost as fast as normally?

But it doesn't mark the method right?


hehe you guessed my following question (it was going to be in another thread, but since you ask).
Yes, (maybe) I would like to mark, for EACH normal message sent:
1) the obejct that receives the message
2) its class
3) the method dictionary
4) the compiled method.

If I first think about normal messages, then:

- 1) and 2) can be done in #normalSend:

normalSend
    "Send a message, starting lookup with the receiver's class."
    "Assume: messageSelector and argumentCount have been set, and that
    the receiver and arguments have been pushed onto the stack,"
    "Note: This method is inlined into the interpreter dispatch loop."
    | rcvr |
    self inline: true.
    self sharedCodeNamed: 'normalSend' inCase: 131.
    rcvr := self internalStackValue: argumentCount.
    self traceObjectUsage: rcvr.
    lkupClass := self fetchClassOf: rcvr.
    receiverClass := lkupClass.
self traceObjectUsage: receiverClass.
    self commonSend.

 


3) I have no idea.

4) I am not sure. I wanted to ask you :)  Maybe  #internalActivateNewMethod is a good place?   Maybe adding a "self markObjectUsage: newMethod"   ?



 It only marks the objects.  However if you analyse the bytecodePrimFoo implementations you should be able to work out which methods are used, SmallInteger>>#+, Float>>#+ et al.


I didn't understand this last sentence.

Thanks Eliot!!


 
 
Or change the part of the bytecode table that specifies the special selector primitives to read
(176 207 sendSpecialSelectorBytecode)

sendSpecialSelectorBytecode
| selectorIndex specialSelectors |
selectorIndex := (currentBytecode - 176) * 2.
specialSelectors := self splObj: SpecialSelectors.
messageSelector := self fetchPointer: selectorIndex
ofObject: specialSelectors.
argumentCount := self fetchInteger: selectorIndex + 1
ofObject: specialSelectors.
self normalSend

But most of all try and slow down and understand what is going on; then you will be able to answer your own questions.  Reading the blue book will help.
 

hehehehehe what an idea :) I didn't know I could do that. Thanks for the blue book. I read the vm chapters but several months ago. I should read it again since the first time I didn't understand very much hehehehe.
 

 
Providing you also look at the perform and method evaluation primitives I think you'll get all sends. 


#primitivePerform*   and #primitiveExecuteMethod*    ???
   
There is another way.  Modify the Smalltalk compiler to to use the special selector sends.


Thanks Eliot for the idea. Can you explain me a little more (sorry, newbie here!). You mean that with the Compiler I can do that all method sends use the normal send instead of special bytecodes or primitives?

Yes.  If you modify the compiler not to use the StdSelectors then the compiler will emit normal sends for all the special selectors.   Again I think if you slowed down and started playing ore you would discover this for yourself and in the end be more productive.  I know its hard and frustrating initially.  But my own competence comes directly from having played around in this way.


Thanks Eliot. I will consider this alternative also.

Best regards.

Mariano
 
best,
Eliot


Thank you very much.

Mariano
 

Thanks a lot in advance,

Mariano



On Sun, Oct 3, 2010 at 11:09 PM, Craig Latta <[hidden email]> wrote:


> Craig Latta has done all this work, talk to him.

    Sure, I'd be happy to discuss it.


-C

--
Craig Latta
www.netjam.org
+ 31 020 894 6247
+  1 415 287 3547
















Reply | Threaded
Open this post in threaded view
|

re: Tracing special messages

ccrraaiigg
In reply to this post by Mariano Martinez Peck
 

Hi Mariano--

     Sorry for the delay. What Eliot said. :)  For what it's worth, my
implementation of option one (from 2003) is in Spoon,
http://netjam.org/spoon/.


-C

--
Craig Latta
www.netjam.org/resume
+ 31 020 894 6247
+  1 415 287 3547