Ideas for CompiledMethod proxies?

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

Ideas for CompiledMethod proxies?

Mariano Martinez Peck
Hi. I am developing kind of proxies for unused compiled methods. I want to detect them, put a proxy instead of them, and swap them to disk. Then, in case they are used, I put back the original ones. With this, I want to realease memory. This is why I need the proxy objects to be as small as possibles.

Right now, I do something like this:

aProxy := CompiledMethodProxyReferenceStreamWithFileName installOn: ClassWith1Var selector: #foo.

this will instantiate the proxy, do the ClassWith1Var methodAt: #foo put: proxy, write the original compiledMethod that was in #foo into a file, etc....

and then if I do "ClassWith1Var new foo", then using the #run:with:in  I load the file from disk and I put back the original method. To know WHICH file I have to load, I have to store the fileName in the proxy object.

In addition, if I DON'T execute the compiled method, but instead I send a message, for example:

(ClassWith1Var >> #foo) literals

this has to do the same: load and put back the original compiled method. To do this, I use the doesNotUnderstand:.

This is easy to do if I store the fileName in the proxy instance. Right now, I am using as fileName this:  CLASS >> SELECTOR. For example, in this case, the file would be named "ClassWith1Var >> #foo"

Now.....with this solution, I need create an proxy instance for each compiled method, and these instances have also another instance for the filename. If I could use the same proxy instance for everybody, the amount of memory released would be muuuuch more. So I thought that maybe from the context I can "guess" the filename if I use conventions.

For example, if you do "ClassWith1Var new foo" then in the #run:with:in I receive all the information to KNOW that the fileName should be "ClassWith1Var >> #foo". So, no problem here.

But for the second case, suppose "(ClassWith1Var >> #foo) literals", I don't see a way to know this.  In this case, #literals is intercepted by the doesNotUnderstand: of my proxy, and here I should load back the original compiled method from disk. The problem is that I cannot know in which CLASS and SELECTOR this proxy was put. The only way I know to do this, is to store the class + selector in the proxy instance....but it is the same...I will need an instance per compiled method. In such case is even easier to directly store the fileName.

Anyway, if someone has a solution or advice on this, I would be appreciated that. I tried with thisContext, but it didn't help me.

Thanks

Mariano
Reply | Threaded
Open this post in threaded view
|

Re: Ideas for CompiledMethod proxies?

Eliot Miranda-2
Hi Mariano,

    it strikes me that the class and selector are implicit in method dictionaries.  So if you use a zero-sized object to replace a method (one word in memory if you make it an instance of a compact class) you can find its class and selector by searching all method dictionaries in the class hierarchy.  In an image with approximately 90,000 methods on a 2.66GHz Core i7 it takes Cog 15 milliseconds on average to locate a method in the hierarchy:

| cms |
cms := CompiledMethod allInstances.
cms := (1 to: cms size by: 100) collect: [:i| cms at: i].
{ Time millisecondsToRun:
[cms do:
[:cm|
[:exit|
ProtoObject withAllSubclasses do:
[:c|
c selectorsAndMethodsDo: [:s :m| m == cm ifTrue: [exit value]]]] valueWithExit]].
 cms size } #(13371 917)
13371 / 917.0 14.58124318429662
CompiledMethod instanceCount 91696

So one thing might be to use a zero-sized object.

Of course you could use a one instance variable object whose instance variable was the class and then things would be /much/ faster, with only one method dictionary to search.

Or perhaps you could use a 4-byte byte array and keep the identity hash of the class and the identity hash of the selector in two 16-bit values in the 4-byte array, but this wouldn't get you anything over and above the one instance variable object pointing to the class.  However, if you are talking abut optimizing a closed world then this does hold water.  One thing you can do if you *really* want to save space is eliminate symbols, replacing them by integers.  The lookup machinery should be able to deal with a SmallInteger selector, and if it doesn't it has a bug.  This is a space saving technique I first heard about in the ActiveBook which used my BrouHaHa VM and ParcPlace's Smalltalk-80 v2.3 back in the 80's to produce an early tablet computer.  So the idea is to number classes and selectors and use the selector numbers to replace symbols.  Now the byte array makes sense because if you have < 64k symbols and < 64k classes you have the class and the selector directly. If you were clever you could put the selector numbering in the compiler and keep the symbol table externally in a file, mapping selector number to symbol there-in.  Obviously the tricky thing is in eliminating or implementing asSymbol in perform: usage.  Sometimes you see horror show code like
    self perform: (self opPrefix, self opSuffix) asSymbol
which makes it /really/ hard to find implementors and senders (and IMO people who write this kind of thing should be shot, and IIRC there is stuff like this in the change notification code, ARGH!!!).

HTH
Eliot

On Fri, Nov 19, 2010 at 12:47 PM, Mariano Martinez Peck <[hidden email]> wrote:
Hi. I am developing kind of proxies for unused compiled methods. I want to detect them, put a proxy instead of them, and swap them to disk. Then, in case they are used, I put back the original ones. With this, I want to realease memory. This is why I need the proxy objects to be as small as possibles.

Right now, I do something like this:

aProxy := CompiledMethodProxyReferenceStreamWithFileName installOn: ClassWith1Var selector: #foo.

this will instantiate the proxy, do the ClassWith1Var methodAt: #foo put: proxy, write the original compiledMethod that was in #foo into a file, etc....

and then if I do "ClassWith1Var new foo", then using the #run:with:in  I load the file from disk and I put back the original method. To know WHICH file I have to load, I have to store the fileName in the proxy object.

In addition, if I DON'T execute the compiled method, but instead I send a message, for example:

(ClassWith1Var >> #foo) literals

this has to do the same: load and put back the original compiled method. To do this, I use the doesNotUnderstand:.

This is easy to do if I store the fileName in the proxy instance. Right now, I am using as fileName this:  CLASS >> SELECTOR. For example, in this case, the file would be named "ClassWith1Var >> #foo"

Now.....with this solution, I need create an proxy instance for each compiled method, and these instances have also another instance for the filename. If I could use the same proxy instance for everybody, the amount of memory released would be muuuuch more. So I thought that maybe from the context I can "guess" the filename if I use conventions.

For example, if you do "ClassWith1Var new foo" then in the #run:with:in I receive all the information to KNOW that the fileName should be "ClassWith1Var >> #foo". So, no problem here.

But for the second case, suppose "(ClassWith1Var >> #foo) literals", I don't see a way to know this.  In this case, #literals is intercepted by the doesNotUnderstand: of my proxy, and here I should load back the original compiled method from disk. The problem is that I cannot know in which CLASS and SELECTOR this proxy was put. The only way I know to do this, is to store the class + selector in the proxy instance....but it is the same...I will need an instance per compiled method. In such case is even easier to directly store the fileName.

Anyway, if someone has a solution or advice on this, I would be appreciated that. I tried with thisContext, but it didn't help me.

Thanks

Mariano

Reply | Threaded
Open this post in threaded view
|

Re: Ideas for CompiledMethod proxies?

Igor Stasenko
In reply to this post by Mariano Martinez Peck
On 19 November 2010 22:47, Mariano Martinez Peck <[hidden email]> wrote:

> Hi. I am developing kind of proxies for unused compiled methods. I want to
> detect them, put a proxy instead of them, and swap them to disk. Then, in
> case they are used, I put back the original ones. With this, I want to
> realease memory. This is why I need the proxy objects to be as small as
> possibles.
>
> Right now, I do something like this:
>
> aProxy := CompiledMethodProxyReferenceStreamWithFileName installOn:
> ClassWith1Var selector: #foo.
>
> this will instantiate the proxy, do the ClassWith1Var methodAt: #foo put:
> proxy, write the original compiledMethod that was in #foo into a file,
> etc....
>
> and then if I do "ClassWith1Var new foo", then using the #run:with:in  I
> load the file from disk and I put back the original method. To know WHICH
> file I have to load, I have to store the fileName in the proxy object.
>
> In addition, if I DON'T execute the compiled method, but instead I send a
> message, for example:
>
> (ClassWith1Var >> #foo) literals
>
> this has to do the same: load and put back the original compiled method. To
> do this, I use the doesNotUnderstand:.
>
> This is easy to do if I store the fileName in the proxy instance. Right now,
> I am using as fileName this:  CLASS >> SELECTOR. For example, in this case,
> the file would be named "ClassWith1Var >> #foo"
>
> Now.....with this solution, I need create an proxy instance for each
> compiled method, and these instances have also another instance for the
> filename. If I could use the same proxy instance for everybody, the amount
> of memory released would be muuuuch more. So I thought that maybe from the
> context I can "guess" the filename if I use conventions.
>
> For example, if you do "ClassWith1Var new foo" then in the #run:with:in I
> receive all the information to KNOW that the fileName should be
> "ClassWith1Var >> #foo". So, no problem here.
>
> But for the second case, suppose "(ClassWith1Var >> #foo) literals", I don't
> see a way to know this.  In this case, #literals is intercepted by the
> doesNotUnderstand: of my proxy, and here I should load back the original
> compiled method from disk. The problem is that I cannot know in which CLASS
> and SELECTOR this proxy was put. The only way I know to do this, is to store
> the class + selector in the proxy instance....but it is the same...I will
> need an instance per compiled method. In such case is even easier to
> directly store the fileName.
>
> Anyway, if someone has a solution or advice on this, I would be appreciated
> that. I tried with thisContext, but it didn't help me.
>

A proxy actually should hold only some unique value (id), or as Eliot
suggested be a unique by itself.
This is enough to find a correspondence between any proxy and its
original method.
You can simply delegate loading the method to some object, which
'knows' how to load a method and where it is stored:

" id based lookup:  "
Proxy>>literals
  | method |
  method := MethodsProxyManager methodFor: id.
  ^ method literals

"or identity based lookup: "

Proxy>>literals
  | method |
  method := MethodsProxyManager methodFor: self.
  ^ method literals

> Thanks
>
> Mariano
>



--
Best regards,
Igor Stasenko AKA sig.

Reply | Threaded
Open this post in threaded view
|

Re: Ideas for CompiledMethod proxies?

Igor Stasenko
Also, here the proxy which can be used to catch all messages (except
those, which optimized by compiler, like #== or #class
and #cannotInterpret:)

:)



--
Best regards,
Igor Stasenko AKA sig.

CVMessageCatchingProxy.st (1K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Ideas for CompiledMethod proxies?

Levente Uzonyi-2
In reply to this post by Mariano Martinez Peck
On Fri, 19 Nov 2010, Mariano Martinez Peck wrote:

> Hi. I am developing kind of proxies for unused compiled methods. I want to
> detect them, put a proxy instead of them, and swap them to disk. Then, in
> case they are used, I put back the original ones. With this, I want to
> realease memory. This is why I need the proxy objects to be as small as
> possibles.
>
> Right now, I do something like this:
>
> aProxy := CompiledMethodProxyReferenceStreamWithFileName installOn:
> ClassWith1Var selector: #foo.
>
> this will instantiate the proxy, do the ClassWith1Var methodAt: #foo put:
> proxy, write the original compiledMethod that was in #foo into a file,
> etc....
>
> and then if I do "ClassWith1Var new foo", then using the #run:with:in  I
> load the file from disk and I put back the original method. To know WHICH
> file I have to load, I have to store the fileName in the proxy object.
>
> In addition, if I DON'T execute the compiled method, but instead I send a
> message, for example:
>
> (ClassWith1Var >> #foo) literals
>
> this has to do the same: load and put back the original compiled method. To
> do this, I use the doesNotUnderstand:.
>
> This is easy to do if I store the fileName in the proxy instance. Right now,
> I am using as fileName this:  CLASS >> SELECTOR. For example, in this case,
> the file would be named "ClassWith1Var >> #foo"
>
> Now.....with this solution, I need create an proxy instance for each
> compiled method, and these instances have also another instance for the
> filename. If I could use the same proxy instance for everybody, the amount
> of memory released would be muuuuch more. So I thought that maybe from the
> context I can "guess" the filename if I use conventions.
>
> For example, if you do "ClassWith1Var new foo" then in the #run:with:in I
> receive all the information to KNOW that the fileName should be
> "ClassWith1Var >> #foo". So, no problem here.
>
> But for the second case, suppose "(ClassWith1Var >> #foo) literals", I don't
> see a way to know this.  In this case, #literals is intercepted by the
> doesNotUnderstand: of my proxy, and here I should load back the original
> compiled method from disk. The problem is that I cannot know in which CLASS
> and SELECTOR this proxy was put. The only way I know to do this, is to store
> the class + selector in the proxy instance....but it is the same...I will
> need an instance per compiled method. In such case is even easier to
> directly store the fileName.
>
> Anyway, if someone has a solution or advice on this, I would be appreciated
> that. I tried with thisContext, but it didn't help me.

In a 15MB image all CompiledMethods use only ~3MB, so this technique
won't save much space IMHO.

To minimize the space usage, use SmallIntegers as proxies. To avoid the
(Object >> #hash) literals problem swap back the real method in
MethodDictionary >> #at:ifAbsent:.
A SmallInteger has 31 bits which can easily identify the file index and
position where the swapped out method is. For example you can use 7 bits
for index and 24 bits for position. That allows you to have 128 files
which can hold 16MB data each.
Or you can store a single method in a file, this way the SmallInteger
identifies the file.


Levente

>
> Thanks
>
> Mariano
>

Reply | Threaded
Open this post in threaded view
|

Re: Ideas for CompiledMethod proxies?

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


On Fri, Nov 19, 2010 at 11:03 PM, Eliot Miranda <[hidden email]> wrote:
Hi Mariano,

    it strikes me that the class and selector are implicit in method dictionaries.  So if you use a zero-sized object to replace a method (one word in memory if you make it an instance of a compact class) you can find its class and selector by searching all method dictionaries in the class hierarchy.  In an image with approximately 90,000 methods on a 2.66GHz Core i7 it takes Cog 15 milliseconds on average to locate a method in the hierarchy:

| cms |
cms := CompiledMethod allInstances.
cms := (1 to: cms size by: 100) collect: [:i| cms at: i].
{ Time millisecondsToRun:
[cms do:
[:cm|
[:exit|
ProtoObject withAllSubclasses do:
[:c|
c selectorsAndMethodsDo: [:s :m| m == cm ifTrue: [exit value]]]] valueWithExit]].
 cms size } #(13371 917)
13371 / 917.0 14.58124318429662
CompiledMethod instanceCount 91696

So one thing might be to use a zero-sized object.

Of course you could use a one instance variable object whose instance variable was the class and then things would be /much/ faster, with only one method dictionary to search.


Thanks Eliot for the idea. I didn't think about searching the method in the whole hierarchy because I thought it was going to be much slower. And its true, storing a pointer to the class will be fast enought.

So...taking into account all the answers I think I should discard the idea of using the SAME proxy instance for everybody and using fileName patterns to guess the file. It seems there is no way. So...if I need an instance per proxy, now let's see how to make this object as small as possible. In the case you told me, the object will be zero sized and if the class is compact, then it would be just one word.
But the "search" will take some time.....if I store the class pointer, then it would be 8 bytes per proxy...

This is why I liked the Levente solution (I answer after to him).
 
Or perhaps you could use a 4-byte byte array and keep the identity hash of the class and the identity hash of the selector in two 16-bit values in the 4-byte array, but this wouldn't get you anything over and above the one instance variable object pointing to the class.  

Exactly. The only thing here is that since I have both, class and selector, and don't need to do the search in the class method dict.
 
However, if you are talking abut optimizing a closed world then this does hold water.  One thing you can do if you *really* want to save space is eliminate symbols, replacing them by integers.  The lookup machinery should be able to deal with a SmallInteger selector, and if it doesn't it has a bug.  This is a space saving technique I first heard about in the ActiveBook which used my BrouHaHa VM and ParcPlace's Smalltalk-80 v2.3 back in the 80's to produce an early tablet computer.  So the idea is to number classes and selectors and use the selector numbers to replace symbols.  Now the byte array makes sense because if you have < 64k symbols and < 64k classes you have the class and the selector directly.

exactly!


If you were clever you could put the selector numbering in the compiler and keep the symbol table externally in a file, mapping selector number to symbol there-in.  Obviously the tricky thing is in eliminating or implementing asSymbol in perform: usage.

ahhhhh  ok, I got the idea :)

Thanks Eliot for the help.
 
 Sometimes you see horror show code like
    self perform: (self opPrefix, self opSuffix) asSymbol
which makes it /really/ hard to find implementors and senders (and IMO people who write this kind of thing should be shot, and IIRC there is stuff like this in the change notification code, ARGH!!!).

HTH
Eliot

On Fri, Nov 19, 2010 at 12:47 PM, Mariano Martinez Peck <[hidden email]> wrote:
Hi. I am developing kind of proxies for unused compiled methods. I want to detect them, put a proxy instead of them, and swap them to disk. Then, in case they are used, I put back the original ones. With this, I want to realease memory. This is why I need the proxy objects to be as small as possibles.

Right now, I do something like this:

aProxy := CompiledMethodProxyReferenceStreamWithFileName installOn: ClassWith1Var selector: #foo.

this will instantiate the proxy, do the ClassWith1Var methodAt: #foo put: proxy, write the original compiledMethod that was in #foo into a file, etc....

and then if I do "ClassWith1Var new foo", then using the #run:with:in  I load the file from disk and I put back the original method. To know WHICH file I have to load, I have to store the fileName in the proxy object.

In addition, if I DON'T execute the compiled method, but instead I send a message, for example:

(ClassWith1Var >> #foo) literals

this has to do the same: load and put back the original compiled method. To do this, I use the doesNotUnderstand:.

This is easy to do if I store the fileName in the proxy instance. Right now, I am using as fileName this:  CLASS >> SELECTOR. For example, in this case, the file would be named "ClassWith1Var >> #foo"

Now.....with this solution, I need create an proxy instance for each compiled method, and these instances have also another instance for the filename. If I could use the same proxy instance for everybody, the amount of memory released would be muuuuch more. So I thought that maybe from the context I can "guess" the filename if I use conventions.

For example, if you do "ClassWith1Var new foo" then in the #run:with:in I receive all the information to KNOW that the fileName should be "ClassWith1Var >> #foo". So, no problem here.

But for the second case, suppose "(ClassWith1Var >> #foo) literals", I don't see a way to know this.  In this case, #literals is intercepted by the doesNotUnderstand: of my proxy, and here I should load back the original compiled method from disk. The problem is that I cannot know in which CLASS and SELECTOR this proxy was put. The only way I know to do this, is to store the class + selector in the proxy instance....but it is the same...I will need an instance per compiled method. In such case is even easier to directly store the fileName.

Anyway, if someone has a solution or advice on this, I would be appreciated that. I tried with thisContext, but it didn't help me.

Thanks

Mariano


Reply | Threaded
Open this post in threaded view
|

Re: Ideas for CompiledMethod proxies?

Mariano Martinez Peck
In reply to this post by Igor Stasenko



A proxy actually should hold only some unique value (id), or as Eliot
suggested be a unique by itself.
This is enough to find a correspondence between any proxy and its
original method.

Yes....but I was wondering if there was a way to use the same proxy instance for everybody and using some conventions, guess which was the original compiled method. Now that that seems not possible, I can use any of these possibilities: id, identity, store class pointer, store a 4bytes array, store the filename directly,  etc....


 
You can simply delegate loading the method to some object, which
'knows' how to load a method and where it is stored:

" id based lookup:  "
Proxy>>literals
 | method |
 method := MethodsProxyManager methodFor: id.
 ^ method literals

"or identity based lookup: "

Proxy>>literals
 | method |
 method := MethodsProxyManager methodFor: self.
 ^ method literals

> Thanks
>
> Mariano
>



--
Best regards,
Igor Stasenko AKA sig.


Reply | Threaded
Open this post in threaded view
|

Re: Ideas for CompiledMethod proxies?

Mariano Martinez Peck
In reply to this post by Levente Uzonyi-2


On Sat, Nov 20, 2010 at 12:34 PM, Levente Uzonyi <[hidden email]> wrote:
On Fri, 19 Nov 2010, Mariano Martinez Peck wrote:

In a 15MB image all CompiledMethods use only ~3MB, so this technique won't save much space IMHO.


mmmmm I thought it was muuuch more. How are you measuring those 3mb ?  Only the compiled method bytearray or also the literals? Because if you take into account all the ByteSymbol instances of literals for example, the size can be more.

 
To minimize the space usage, use SmallIntegers as proxies. To avoid the (Object >> #hash) literals

#literals was an example, but the same happens with all the methods implemented in CompiledMethod.
 
problem swap back the real method in MethodDictionary >> #at:ifAbsent:.

Yes, actually Luc had this idea too. I should also modify (or implement) #at:  and friends
What I was afraid is if the VM directly access to them and I cannot interpret them. Is this possible?  I think the vm access them but only when executing them....where in such case, it will end up with a #run:with:in, which is perfect for me. 


A SmallInteger has 31 bits which can easily identify the file index and position where the swapped out method is. For example you can use 7 bits for index and 24 bits for position. That allows you to have 128 files which can hold 16MB data each.
Or you can store a single method in a file, this way the SmallInteger identifies the file.

Yes, exactly :)

Thanks Levente. I like this idea. I've been doing proxies for classes, normal objects, etc and I never thought about using SmallIntegers. This is because I usually need to do a #become:   between the original object and the proxy. But in this case this is not needed, since I just need a methodDict at: put: .  And this is a good idea because I don't need an object header per proxy instance.

I will try to implement this. Thank you very much for all the answers.

Mariano
 


Levente


Thanks

Mariano



Reply | Threaded
Open this post in threaded view
|

Re: Ideas for CompiledMethod proxies?

Levente Uzonyi-2
On Sat, 20 Nov 2010, Mariano Martinez Peck wrote:

> On Sat, Nov 20, 2010 at 12:34 PM, Levente Uzonyi <[hidden email]> wrote:
>
>> On Fri, 19 Nov 2010, Mariano Martinez Peck wrote:
>>
>> In a 15MB image all CompiledMethods use only ~3MB, so this technique won't
>> save much space IMHO.
>>
>>
> mmmmm I thought it was muuuch more. How are you measuring those 3mb ?  Only
> the compiled method bytearray or also the literals? Because if you take into
> account all the ByteSymbol instances of literals for example, the size can
> be more.

That's just the methods themselves. I did some more experiments and I
think the savings can peak at ~5MB for the 15MB image.

>
>
>
>> To minimize the space usage, use SmallIntegers as proxies. To avoid the
>> (Object >> #hash) literals
>
>
> #literals was an example, but the same happens with all the methods
> implemented in CompiledMethod.

I also used #literals as an example. :)

>
>
>> problem swap back the real method in MethodDictionary >> #at:ifAbsent:.
>>
>
> Yes, actually Luc had this idea too. I should also modify (or implement)
> #at:  and friends
> What I was afraid is if the VM directly access to them and I cannot
> interpret them. Is this possible?  I think the vm access them but only when
> executing them....where in such case, it will end up with a #run:with:in,
> which is perfect for me.

Normally the send ends up in #run:with:in:.

>
>
> A SmallInteger has 31 bits which can easily identify the file index and
>> position where the swapped out method is. For example you can use 7 bits for
>> index and 24 bits for position. That allows you to have 128 files which can
>> hold 16MB data each.
>> Or you can store a single method in a file, this way the SmallInteger
>> identifies the file.
>>
>
> Yes, exactly :)
>
> Thanks Levente. I like this idea. I've been doing proxies for classes,
> normal objects, etc and I never thought about using SmallIntegers. This is
> because I usually need to do a #become:   between the original object and
> the proxy. But in this case this is not needed, since I just need a
> methodDict at: put: .  And this is a good idea because I don't need an
> object header per proxy instance.
>
> I will try to implement this. Thank you very much for all the answers.

I did a quick implementation and it works. The only problem is that you
can't swap-out a method that's used by the swap-in code.


Levente

>
> Mariano
>
>
>>
>>
>> Levente
>>
>>
>>> Thanks
>>>
>>> Mariano
>>>
>>>
>>
>

Reply | Threaded
Open this post in threaded view
|

Re: Ideas for CompiledMethod proxies?

Mariano Martinez Peck


On Sat, Nov 20, 2010 at 5:41 PM, Levente Uzonyi <[hidden email]> wrote:
On Sat, 20 Nov 2010, Mariano Martinez Peck wrote:

On Sat, Nov 20, 2010 at 12:34 PM, Levente Uzonyi <[hidden email]> wrote:

On Fri, 19 Nov 2010, Mariano Martinez Peck wrote:

In a 15MB image all CompiledMethods use only ~3MB, so this technique won't
save much space IMHO.


mmmmm I thought it was muuuch more. How are you measuring those 3mb ?  Only
the compiled method bytearray or also the literals? Because if you take into
account all the ByteSymbol instances of literals for example, the size can
be more.

That's just the methods themselves. I did some more experiments and I think the savings can peak at ~5MB for the 15MB image.

Now it sounds better :)   More similar to my calculations....arround 1/3 part of the image.
 





To minimize the space usage, use SmallIntegers as proxies. To avoid the
(Object >> #hash) literals


#literals was an example, but the same happens with all the methods
implemented in CompiledMethod.

I also used #literals as an example. :)

excellent
 




problem swap back the real method in MethodDictionary >> #at:ifAbsent:.


Yes, actually Luc had this idea too. I should also modify (or implement)
#at:  and friends
What I was afraid is if the VM directly access to them and I cannot
interpret them. Is this possible?  I think the vm access them but only when
executing them....where in such case, it will end up with a #run:with:in,
which is perfect for me.

Normally the send ends up in #run:with:in:.



Excellent. No problems then.
 



A SmallInteger has 31 bits which can easily identify the file index and
position where the swapped out method is. For example you can use 7 bits for
index and 24 bits for position. That allows you to have 128 files which can
hold 16MB data each.
Or you can store a single method in a file, this way the SmallInteger
identifies the file.


Yes, exactly :)

Thanks Levente. I like this idea. I've been doing proxies for classes,
normal objects, etc and I never thought about using SmallIntegers. This is
because I usually need to do a #become:   between the original object and
the proxy. But in this case this is not needed, since I just need a
methodDict at: put: .  And this is a good idea because I don't need an
object header per proxy instance.

I will try to implement this. Thank you very much for all the answers.

I did a quick implementation and it works.

I am implementing right now :)

 
The only problem is that you can't swap-out a method that's used by the swap-in code.


Yes, but that's easy to solve. Before swapping everything, I "simulate" the swapping of a dummy CompiledMethod. During that, I mark all the CompiledMethods that were used to perform that. And then, I exclude those objects from being swapped :)
 

Levente


Mariano




Levente


Thanks

Mariano






Reply | Threaded
Open this post in threaded view
|

Re: Ideas for CompiledMethod proxies?

Mariano Martinez Peck
In reply to this post by Levente Uzonyi-2


Thanks Levente. I like this idea. I've been doing proxies for classes,
normal objects, etc and I never thought about using SmallIntegers. This is
because I usually need to do a #become:   between the original object and
the proxy. But in this case this is not needed, since I just need a
methodDict at: put: .  And this is a good idea because I don't need an
object header per proxy instance.

I will try to implement this. Thank you very much for all the answers.

I did a quick implementation and it works. The only problem is that you can't swap-out a method that's used by the swap-in code.


It doesn't work here. It seems I cannot use SmallInteger like methods. The #run:with:in: is never call and the image crashes.

Example (be carefull, it may crash your image):

TestCase methodDict at: #assert: put: 4.
TestCase new assert: 'zaraza'.

I am checking the VM side now to see if I find something.

Cheers

Mariano

 

Levente


Mariano




Levente


Thanks

Mariano






Reply | Threaded
Open this post in threaded view
|

Re: Ideas for CompiledMethod proxies?

Eliot Miranda-2


On Sat, Nov 20, 2010 at 10:28 AM, Mariano Martinez Peck <[hidden email]> wrote:


Thanks Levente. I like this idea. I've been doing proxies for classes,
normal objects, etc and I never thought about using SmallIntegers. This is
because I usually need to do a #become:   between the original object and
the proxy. But in this case this is not needed, since I just need a
methodDict at: put: .  And this is a good idea because I don't need an
object header per proxy instance.

I will try to implement this. Thank you very much for all the answers.

I did a quick implementation and it works. The only problem is that you can't swap-out a method that's used by the swap-in code.


It doesn't work here. It seems I cannot use SmallInteger like methods. The #run:with:in: is never call and the image crashes.

That's simply a bug and we should fix it.  What crashes, the Interpreter, Cog or both?  Prepare a reproducible test case (image, change set etc) and we can try and fix this.

best
Eliot
 

Example (be carefull, it may crash your image):

TestCase methodDict at: #assert: put: 4.
TestCase new assert: 'zaraza'.

I am checking the VM side now to see if I find something.

Cheers

Mariano

 

Levente


Mariano




Levente


Thanks

Mariano







Reply | Threaded
Open this post in threaded view
|

Re: Ideas for CompiledMethod proxies?

Levente Uzonyi-2
In reply to this post by Mariano Martinez Peck
On Sat, 20 Nov 2010, Mariano Martinez Peck wrote:

> On Sat, Nov 20, 2010 at 5:41 PM, Levente Uzonyi <[hidden email]> wrote:
>> The only problem is that you can't swap-out a method that's used by the
>> swap-in code.
>>
>>
> Yes, but that's easy to solve. Before swapping everything, I "simulate" the
> swapping of a dummy CompiledMethod. During that, I mark all the
> CompiledMethods that were used to perform that. And then, I exclude those
> objects from being swapped :)

That won't work, because during the simulation you'll only try a single
execution path. Swapping in a real method may invoke methods that weren't
used during the simulation. For example my implementation uses
#storeString to serialize the methods and Compiler >> #evaluate: to
deserialize them. So during deserialization a lot of different methods may
be invoked.


Levente


Reply | Threaded
Open this post in threaded view
|

Re: Ideas for CompiledMethod proxies?

Mariano Martinez Peck


On Sun, Nov 21, 2010 at 12:13 AM, Levente Uzonyi <[hidden email]> wrote:
On Sat, 20 Nov 2010, Mariano Martinez Peck wrote:

On Sat, Nov 20, 2010 at 5:41 PM, Levente Uzonyi <[hidden email]> wrote:
The only problem is that you can't swap-out a method that's used by the
swap-in code.


Yes, but that's easy to solve. Before swapping everything, I "simulate" the
swapping of a dummy CompiledMethod. During that, I mark all the
CompiledMethods that were used to perform that. And then, I exclude those
objects from being swapped :)

That won't work, because during the simulation you'll only try a single execution path. Swapping in a real method may invoke methods that weren't used during the simulation. For example my implementation uses #storeString to serialize the methods and Compiler >> #evaluate: to deserialize them. So during deserialization a lot of different methods may be invoked.

Ahhh I got it....

Are you using Cog?  because with the SmallInteger I have the problem I described with #run:with:in: 

Last question....to use SmallIntegers, I need to put some methods in SmallInteger, like #run:with:in:  , #doesNotUnderstand: ,  and all the methods related to writing and loading back the original compiledMethod.  Of course I can put all those methods under a category  *MyProxyPackage  ... but I was thinking if there is another way. I would love to have MySmallIntegerProxy that extends from ProtoObject (because I want my proxy to understand as less messages as possible) and that is threated by the VM like a SmallInetger, I mean, that it directly stores the number value in the address, and put the last bit in 1.

Is this possible? how much work can it be?
 
Thanks in advance,

Mariano

Reply | Threaded
Open this post in threaded view
|

Re: Ideas for CompiledMethod proxies?

Igor Stasenko
Obviously you can't having a single object representation (a tagged
machine word with lowest bit set)
and have two different classes for it.

On 21 November 2010 16:51, Mariano Martinez Peck <[hidden email]> wrote:

>
>
> On Sun, Nov 21, 2010 at 12:13 AM, Levente Uzonyi <[hidden email]> wrote:
>>
>> On Sat, 20 Nov 2010, Mariano Martinez Peck wrote:
>>
>>> On Sat, Nov 20, 2010 at 5:41 PM, Levente Uzonyi <[hidden email]> wrote:
>>>>
>>>> The only problem is that you can't swap-out a method that's used by the
>>>> swap-in code.
>>>>
>>>>
>>> Yes, but that's easy to solve. Before swapping everything, I "simulate"
>>> the
>>> swapping of a dummy CompiledMethod. During that, I mark all the
>>> CompiledMethods that were used to perform that. And then, I exclude those
>>> objects from being swapped :)
>>
>> That won't work, because during the simulation you'll only try a single
>> execution path. Swapping in a real method may invoke methods that weren't
>> used during the simulation. For example my implementation uses #storeString
>> to serialize the methods and Compiler >> #evaluate: to deserialize them. So
>> during deserialization a lot of different methods may be invoked.
>
> Ahhh I got it....
>
> Are you using Cog?  because with the SmallInteger I have the problem I
> described with #run:with:in:
>
> Last question....to use SmallIntegers, I need to put some methods in
> SmallInteger, like #run:with:in:  , #doesNotUnderstand: ,  and all the
> methods related to writing and loading back the original compiledMethod.  Of
> course I can put all those methods under a category  *MyProxyPackage  ...
> but I was thinking if there is another way. I would love to have
> MySmallIntegerProxy that extends from ProtoObject (because I want my proxy
> to understand as less messages as possible) and that is threated by the VM
> like a SmallInetger, I mean, that it directly stores the number value in the
> address, and put the last bit in 1.
>
> Is this possible? how much work can it be?
>
> Thanks in advance,
>
> Mariano
>
>



--
Best regards,
Igor Stasenko AKA sig.

Reply | Threaded
Open this post in threaded view
|

Re: Ideas for CompiledMethod proxies?

Mariano Martinez Peck


On Sun, Nov 21, 2010 at 5:31 PM, Igor Stasenko <[hidden email]> wrote:
Obviously you can't having a single object representation (a tagged
machine word with lowest bit set)
and have two different classes for it.


Yes, that's true. The thing is that I have a big problem using SmallInteger as proxies....So far I always used a subclass of ProtoObject for the proxies. This is cool because most of the messages are not understood by ProtoObject, thus I can intercept most messages. Now, the problem using SmallInteger as proxies is that there are several methods that ARE understood by both. This is a big problem because the original CompiledMethod is not installed, and the method answers but with a different value.

For example, suppose I do something like this:

MyClass methodDict at: #foo put: 5.
(MyClass >> #foo) size

In this case, I would like that size is NOT understood by the proxy and that loads back the original compiled method. But this is not the case since SmallIngeger DOES understand the message #size. Thus, it answers...and something different than the size of the compiled method...

So in summary I have problems with all methods that are understood by both, even all those in Object I think...

Best regards,

Mariano

 
On 21 November 2010 16:51, Mariano Martinez Peck <[hidden email]> wrote:
>
>
> On Sun, Nov 21, 2010 at 12:13 AM, Levente Uzonyi <[hidden email]> wrote:
>>
>> On Sat, 20 Nov 2010, Mariano Martinez Peck wrote:
>>
>>> On Sat, Nov 20, 2010 at 5:41 PM, Levente Uzonyi <[hidden email]> wrote:
>>>>
>>>> The only problem is that you can't swap-out a method that's used by the
>>>> swap-in code.
>>>>
>>>>
>>> Yes, but that's easy to solve. Before swapping everything, I "simulate"
>>> the
>>> swapping of a dummy CompiledMethod. During that, I mark all the
>>> CompiledMethods that were used to perform that. And then, I exclude those
>>> objects from being swapped :)
>>
>> That won't work, because during the simulation you'll only try a single
>> execution path. Swapping in a real method may invoke methods that weren't
>> used during the simulation. For example my implementation uses #storeString
>> to serialize the methods and Compiler >> #evaluate: to deserialize them. So
>> during deserialization a lot of different methods may be invoked.
>
> Ahhh I got it....
>
> Are you using Cog?  because with the SmallInteger I have the problem I
> described with #run:with:in:
>
> Last question....to use SmallIntegers, I need to put some methods in
> SmallInteger, like #run:with:in:  , #doesNotUnderstand: ,  and all the
> methods related to writing and loading back the original compiledMethod.  Of
> course I can put all those methods under a category  *MyProxyPackage  ...
> but I was thinking if there is another way. I would love to have
> MySmallIntegerProxy that extends from ProtoObject (because I want my proxy
> to understand as less messages as possible) and that is threated by the VM
> like a SmallInetger, I mean, that it directly stores the number value in the
> address, and put the last bit in 1.
>
> Is this possible? how much work can it be?
>
> Thanks in advance,
>
> Mariano
>
>



--
Best regards,
Igor Stasenko AKA sig.


Reply | Threaded
Open this post in threaded view
|

Re: Ideas for CompiledMethod proxies?

Levente Uzonyi-2
On Tue, 30 Nov 2010, Mariano Martinez Peck wrote:

> On Sun, Nov 21, 2010 at 5:31 PM, Igor Stasenko <[hidden email]> wrote:
>
>> Obviously you can't having a single object representation (a tagged
>> machine word with lowest bit set)
>> and have two different classes for it.
>>
>>
> Yes, that's true. The thing is that I have a big problem using SmallInteger
> as proxies....So far I always used a subclass of ProtoObject for the
> proxies. This is cool because most of the messages are not understood by
> ProtoObject, thus I can intercept most messages. Now, the problem using
> SmallInteger as proxies is that there are several methods that ARE
> understood by both. This is a big problem because the original
> CompiledMethod is not installed, and the method answers but with a different
> value.
>
> For example, suppose I do something like this:
>
> MyClass methodDict at: #foo put: 5.
> (MyClass >> #foo) size
>
> In this case, I would like that size is NOT understood by the proxy and that
> loads back the original compiled method. But this is not the case since
> SmallIngeger DOES understand the message #size. Thus, it answers...and
> something different than the size of the compiled method...


That's why you should change MethodDictionary >> #at:ifAbsent: to load
the CompiledMethod and return that instead of the integer.


Levente

>
> So in summary I have problems with all methods that are understood by both,
> even all those in Object I think...
>
> Best regards,
>
> Mariano
>
>
>
>> On 21 November 2010 16:51, Mariano Martinez Peck <[hidden email]>
>> wrote:
>>>
>>>
>>> On Sun, Nov 21, 2010 at 12:13 AM, Levente Uzonyi <[hidden email]> wrote:
>>>>
>>>> On Sat, 20 Nov 2010, Mariano Martinez Peck wrote:
>>>>
>>>>> On Sat, Nov 20, 2010 at 5:41 PM, Levente Uzonyi <[hidden email]> wrote:
>>>>>>
>>>>>> The only problem is that you can't swap-out a method that's used by
>> the
>>>>>> swap-in code.
>>>>>>
>>>>>>
>>>>> Yes, but that's easy to solve. Before swapping everything, I "simulate"
>>>>> the
>>>>> swapping of a dummy CompiledMethod. During that, I mark all the
>>>>> CompiledMethods that were used to perform that. And then, I exclude
>> those
>>>>> objects from being swapped :)
>>>>
>>>> That won't work, because during the simulation you'll only try a single
>>>> execution path. Swapping in a real method may invoke methods that
>> weren't
>>>> used during the simulation. For example my implementation uses
>> #storeString
>>>> to serialize the methods and Compiler >> #evaluate: to deserialize them.
>> So
>>>> during deserialization a lot of different methods may be invoked.
>>>
>>> Ahhh I got it....
>>>
>>> Are you using Cog?  because with the SmallInteger I have the problem I
>>> described with #run:with:in:
>>>
>>> Last question....to use SmallIntegers, I need to put some methods in
>>> SmallInteger, like #run:with:in:  , #doesNotUnderstand: ,  and all the
>>> methods related to writing and loading back the original compiledMethod.
>> Of
>>> course I can put all those methods under a category  *MyProxyPackage  ...
>>> but I was thinking if there is another way. I would love to have
>>> MySmallIntegerProxy that extends from ProtoObject (because I want my
>> proxy
>>> to understand as less messages as possible) and that is threated by the
>> VM
>>> like a SmallInetger, I mean, that it directly stores the number value in
>> the
>>> address, and put the last bit in 1.
>>>
>>> Is this possible? how much work can it be?
>>>
>>> Thanks in advance,
>>>
>>> Mariano
>>>
>>>
>>
>>
>>
>> --
>> Best regards,
>> Igor Stasenko AKA sig.
>>
>>
>

Reply | Threaded
Open this post in threaded view
|

Re: Ideas for CompiledMethod proxies?

Mariano Martinez Peck


On Tue, Nov 30, 2010 at 12:52 PM, Levente Uzonyi <[hidden email]> wrote:
On Tue, 30 Nov 2010, Mariano Martinez Peck wrote:

On Sun, Nov 21, 2010 at 5:31 PM, Igor Stasenko <[hidden email]> wrote:

Obviously you can't having a single object representation (a tagged
machine word with lowest bit set)
and have two different classes for it.


Yes, that's true. The thing is that I have a big problem using SmallInteger
as proxies....So far I always used a subclass of ProtoObject for the
proxies. This is cool because most of the messages are not understood by
ProtoObject, thus I can intercept most messages. Now, the problem using
SmallInteger as proxies is that there are several methods that ARE
understood by both. This is a big problem because the original
CompiledMethod is not installed, and the method answers but with a different
value.

For example, suppose I do something like this:

MyClass methodDict at: #foo put: 5.
(MyClass >> #foo) size

In this case, I would like that size is NOT understood by the proxy and that
loads back the original compiled method. But this is not the case since
SmallIngeger DOES understand the message #size. Thus, it answers...and
something different than the size of the compiled method...


That's why you should change MethodDictionary >> #at:ifAbsent: to load the CompiledMethod and return that instead of the integer.


Uffff sorry Levente. You are totally right. I forgot we already discussed this...
Even more, now I checked my MethodDictionary #at:ifAbsent:  and I have:


at: key ifAbsent: aBlock

    | index value |
    index := self findElementOrNil: key.
    (self basicAt: index) == nil ifTrue: [ ^ aBlock value ].
    value := array at: index.
    "(value isProxy) ifTrue: [value mareaUninstall]."
    ^ array at: index


notice the comment ;)

Thanks!!!

Mariano

 

Levente



So in summary I have problems with all methods that are understood by both,
even all those in Object I think...

Best regards,

Mariano



On 21 November 2010 16:51, Mariano Martinez Peck <[hidden email]>
wrote:


On Sun, Nov 21, 2010 at 12:13 AM, Levente Uzonyi <[hidden email]> wrote:

On Sat, 20 Nov 2010, Mariano Martinez Peck wrote:

On Sat, Nov 20, 2010 at 5:41 PM, Levente Uzonyi <[hidden email]> wrote:

The only problem is that you can't swap-out a method that's used by
the
swap-in code.


Yes, but that's easy to solve. Before swapping everything, I "simulate"
the
swapping of a dummy CompiledMethod. During that, I mark all the
CompiledMethods that were used to perform that. And then, I exclude
those
objects from being swapped :)

That won't work, because during the simulation you'll only try a single
execution path. Swapping in a real method may invoke methods that
weren't
used during the simulation. For example my implementation uses
#storeString
to serialize the methods and Compiler >> #evaluate: to deserialize them.
So
during deserialization a lot of different methods may be invoked.

Ahhh I got it....

Are you using Cog?  because with the SmallInteger I have the problem I
described with #run:with:in:

Last question....to use SmallIntegers, I need to put some methods in
SmallInteger, like #run:with:in:  , #doesNotUnderstand: ,  and all the
methods related to writing and loading back the original compiledMethod.
Of
course I can put all those methods under a category  *MyProxyPackage  ...
but I was thinking if there is another way. I would love to have
MySmallIntegerProxy that extends from ProtoObject (because I want my
proxy
to understand as less messages as possible) and that is threated by the
VM
like a SmallInetger, I mean, that it directly stores the number value in
the
address, and put the last bit in 1.

Is this possible? how much work can it be?

Thanks in advance,

Mariano





--
Best regards,
Igor Stasenko AKA sig.





Reply | Threaded
Open this post in threaded view
|

Re: Ideas for CompiledMethod proxies?

Igor Stasenko
On 30 November 2010 14:53, Mariano Martinez Peck <[hidden email]> wrote:

>
>
> On Tue, Nov 30, 2010 at 12:52 PM, Levente Uzonyi <[hidden email]> wrote:
>>
>> On Tue, 30 Nov 2010, Mariano Martinez Peck wrote:
>>
>>> On Sun, Nov 21, 2010 at 5:31 PM, Igor Stasenko <[hidden email]>
>>> wrote:
>>>
>>>> Obviously you can't having a single object representation (a tagged
>>>> machine word with lowest bit set)
>>>> and have two different classes for it.
>>>>
>>>>
>>> Yes, that's true. The thing is that I have a big problem using
>>> SmallInteger
>>> as proxies....So far I always used a subclass of ProtoObject for the
>>> proxies. This is cool because most of the messages are not understood by
>>> ProtoObject, thus I can intercept most messages. Now, the problem using
>>> SmallInteger as proxies is that there are several methods that ARE
>>> understood by both. This is a big problem because the original
>>> CompiledMethod is not installed, and the method answers but with a
>>> different
>>> value.
>>>
>>> For example, suppose I do something like this:
>>>
>>> MyClass methodDict at: #foo put: 5.
>>> (MyClass >> #foo) size
>>>
>>> In this case, I would like that size is NOT understood by the proxy and
>>> that
>>> loads back the original compiled method. But this is not the case since
>>> SmallIngeger DOES understand the message #size. Thus, it answers...and
>>> something different than the size of the compiled method...
>>
>>
>> That's why you should change MethodDictionary >> #at:ifAbsent: to load the
>> CompiledMethod and return that instead of the integer.
>>
>
> Uffff sorry Levente. You are totally right. I forgot we already discussed
> this...
> Even more, now I checked my MethodDictionary #at:ifAbsent:  and I have:
>
>
> at: key ifAbsent: aBlock
>
>     | index value |
>     index := self findElementOrNil: key.
>     (self basicAt: index) == nil ifTrue: [ ^ aBlock value ].
>     value := array at: index.
>     "(value isProxy) ifTrue: [value mareaUninstall]."
>     ^ array at: index
>
.. and then you need to change #do: , #associationsDo: etc etc..

>
> notice the comment ;)
>
> Thanks!!!
>
> Mariano
>
>
>>
>> Levente
>>
>>>
>>> So in summary I have problems with all methods that are understood by
>>> both,
>>> even all those in Object I think...
>>>
>>> Best regards,
>>>
>>> Mariano
>>>
>>>
>>>
>>>> On 21 November 2010 16:51, Mariano Martinez Peck <[hidden email]>
>>>> wrote:
>>>>>
>>>>>
>>>>> On Sun, Nov 21, 2010 at 12:13 AM, Levente Uzonyi <[hidden email]> wrote:
>>>>>>
>>>>>> On Sat, 20 Nov 2010, Mariano Martinez Peck wrote:
>>>>>>
>>>>>>> On Sat, Nov 20, 2010 at 5:41 PM, Levente Uzonyi <[hidden email]>
>>>>>>> wrote:
>>>>>>>>
>>>>>>>> The only problem is that you can't swap-out a method that's used by
>>>>
>>>> the
>>>>>>>>
>>>>>>>> swap-in code.
>>>>>>>>
>>>>>>>>
>>>>>>> Yes, but that's easy to solve. Before swapping everything, I
>>>>>>> "simulate"
>>>>>>> the
>>>>>>> swapping of a dummy CompiledMethod. During that, I mark all the
>>>>>>> CompiledMethods that were used to perform that. And then, I exclude
>>>>
>>>> those
>>>>>>>
>>>>>>> objects from being swapped :)
>>>>>>
>>>>>> That won't work, because during the simulation you'll only try a
>>>>>> single
>>>>>> execution path. Swapping in a real method may invoke methods that
>>>>
>>>> weren't
>>>>>>
>>>>>> used during the simulation. For example my implementation uses
>>>>
>>>> #storeString
>>>>>>
>>>>>> to serialize the methods and Compiler >> #evaluate: to deserialize
>>>>>> them.
>>>>
>>>> So
>>>>>>
>>>>>> during deserialization a lot of different methods may be invoked.
>>>>>
>>>>> Ahhh I got it....
>>>>>
>>>>> Are you using Cog?  because with the SmallInteger I have the problem I
>>>>> described with #run:with:in:
>>>>>
>>>>> Last question....to use SmallIntegers, I need to put some methods in
>>>>> SmallInteger, like #run:with:in:  , #doesNotUnderstand: ,  and all the
>>>>> methods related to writing and loading back the original
>>>>> compiledMethod.
>>>>
>>>> Of
>>>>>
>>>>> course I can put all those methods under a category  *MyProxyPackage
>>>>>  ...
>>>>> but I was thinking if there is another way. I would love to have
>>>>> MySmallIntegerProxy that extends from ProtoObject (because I want my
>>>>
>>>> proxy
>>>>>
>>>>> to understand as less messages as possible) and that is threated by the
>>>>
>>>> VM
>>>>>
>>>>> like a SmallInetger, I mean, that it directly stores the number value
>>>>> in
>>>>
>>>> the
>>>>>
>>>>> address, and put the last bit in 1.
>>>>>
>>>>> Is this possible? how much work can it be?
>>>>>
>>>>> Thanks in advance,
>>>>>
>>>>> Mariano
>>>>>
>>>>>
>>>>
>>>>
>>>>
>>>> --
>>>> Best regards,
>>>> Igor Stasenko AKA sig.
>>>>
>>>>
>>>
>>
>
>



--
Best regards,
Igor Stasenko AKA sig.

Reply | Threaded
Open this post in threaded view
|

Re: Ideas for CompiledMethod proxies?

Levente Uzonyi-2
On Tue, 30 Nov 2010, Igor Stasenko wrote:

> .. and then you need to change #do: , #associationsDo: etc etc..

Or he can subclass MethodDictionary and override those methods.


Levente

12