pharo-users@lists.pharo.org

Any question about pharo is welcome

View all threads

Need Help with Changing Message Sends in Compiled Blocks

SJ
Sebastian Jordan
Mon, Dec 30, 2024 11:55 AM

TL;DR: I need help changing the message OrderedCollection new to OrderedCollection --> newTenured <-- at a specific offset in a compiled block. I can do this for regular methods, but I get an error when the method is a Block.

Hello everyone,

I'm trying to automatically change message sends in my code, but I'm having trouble with compiled blocks.
For example, I want to change the message OrderedCollection new to OrderedCollection --> newTenured <-- in a specific method. I have the compiled block and the offset (26) for the message I want to change. However, searching for the selector new doesn't work because there can be multiple messages with the same name, and I only want to change the one at the given offset.

theMethod

| tmp1 |
1 = tmp1 something: [ "rewrite this message send" OrderedCollection new ].
tmp1 otherStruf: [ Dictionary new "do not rewrite this meesage send" ].
^ self

I can change the message when there is no block without any problem using the IR like this:

transformMessageSend: compiledMethodOrBlock offset: offset

| oldSelector newSelector irSendNode ir irSequences |
oldSelector := (compiledMethodOrBlock sourceNode sourceNodeForPC: offset) selector.
newSelector := self makeNewSelector: oldSelector.

ir := compiledMethodOrBlock ir.
irSequences := ir allSequences flatCollect: #children.
irSendNode := (irSequences select: #isSend) detect: [ :e | e selector = oldSelector ].
irSendNode selector: newSelector.

^ ir generate
      selector: compiledMethodOrBlock selector;
      yourself

But I get an error with ir generate when the compiledMethodOrBlock is a Block. If it's a normal compiled method, it works as expected.
Can anyone help me with this? Thanks!

PS: I'm not forced to do it with the IR, ir can be done by using the AST. The only thing is that I'd like to avoid doing string manipulation

Cheers and merry christmas,
Sebastian Jordan

TL;DR: I need help changing the message OrderedCollection new to OrderedCollection --> newTenured <-- at a specific offset in a compiled block. I can do this for regular methods, but I get an error when the method is a Block. Hello everyone, I'm trying to automatically change message sends in my code, but I'm having trouble with compiled blocks. For example, I want to change the message OrderedCollection new to OrderedCollection --> newTenured <-- in a specific method. I have the compiled block and the offset (26) for the message I want to change. However, searching for the selector new doesn't work because there can be multiple messages with the same name, and I only want to change the one at the given offset. theMethod | tmp1 | 1 = tmp1 something: [ "rewrite this message send" OrderedCollection new ]. tmp1 otherStruf: [ Dictionary new "do not rewrite this meesage send" ]. ^ self I can change the message when there is no block without any problem using the IR like this: transformMessageSend: compiledMethodOrBlock offset: offset | oldSelector newSelector irSendNode ir irSequences | oldSelector := (compiledMethodOrBlock sourceNode sourceNodeForPC: offset) selector. newSelector := self makeNewSelector: oldSelector. ir := compiledMethodOrBlock ir. irSequences := ir allSequences flatCollect: #children. irSendNode := (irSequences select: #isSend) detect: [ :e | e selector = oldSelector ]. irSendNode selector: newSelector. ^ ir generate selector: compiledMethodOrBlock selector; yourself But I get an error with ir generate when the compiledMethodOrBlock is a Block. If it's a normal compiled method, it works as expected. Can anyone help me with this? Thanks! PS: I'm not forced to do it with the IR, ir can be done by using the AST. The only thing is that I'd like to avoid doing string manipulation Cheers and merry christmas, Sebastian Jordan
TM
Tim Mackinnon
Mon, Dec 30, 2024 8:11 PM

I’m not totally clear on what you are trying to do, but have you looked at the rewrite tool, that is meant for this kind of thing?
The online help is reasonable good for this and there are quite a few msgs here describing it. You should be able to match the change you want and also limit the scope of the change,

Tim

On 30 Dec 2024, at 12:56, Sebastian Jordan sebastian.jordan@inria.fr wrote:

TL;DR: I need help changing the message OrderedCollection new to OrderedCollection --> newTenured <-- at a specific offset in a compiled block. I can do this for regular methods, but I get an error when the method is a Block.

Hello everyone,

I'm trying to automatically change message sends in my code, but I'm having trouble with compiled blocks.
For example, I want to change the message OrderedCollection new to OrderedCollection --> newTenured <-- in a specific method. I have the compiled block and the offset (26) for the message I want to change. However, searching for the selector new doesn't work because there can be multiple messages with the same name, and I only want to change the one at the given offset.

theMethod

| tmp1 |
1 = tmp1 something: [ "rewrite this message send" OrderedCollection new ].
tmp1 otherStruf: [ Dictionary new "do not rewrite this meesage send" ].
^ self

I can change the message when there is no block without any problem using the IR like this:

transformMessageSend: compiledMethodOrBlock offset: offset

| oldSelector newSelector irSendNode ir irSequences |
oldSelector := (compiledMethodOrBlock sourceNode sourceNodeForPC: offset) selector.
newSelector := self makeNewSelector: oldSelector.

ir := compiledMethodOrBlock ir.
irSequences := ir allSequences flatCollect: #children.
irSendNode := (irSequences select: #isSend) detect: [ :e | e selector = oldSelector ].
irSendNode selector: newSelector.

^ ir generate
      selector: compiledMethodOrBlock selector;
      yourself

But I get an error with ir generate when the compiledMethodOrBlock is a Block. If it's a normal compiled method, it works as expected.
Can anyone help me with this? Thanks!

PS: I'm not forced to do it with the IR, ir can be done by using the AST. The only thing is that I'd like to avoid doing string manipulation

Cheers and merry christmas,
Sebastian Jordan

I’m not totally clear on what you are trying to do, but have you looked at the rewrite tool, that is meant for this kind of thing? The online help is reasonable good for this and there are quite a few msgs here describing it. You should be able to match the change you want and also limit the scope of the change, Tim > On 30 Dec 2024, at 12:56, Sebastian Jordan <sebastian.jordan@inria.fr> wrote: > > TL;DR: I need help changing the message OrderedCollection new to OrderedCollection --> newTenured <-- at a specific offset in a compiled block. I can do this for regular methods, but I get an error when the method is a Block. > > Hello everyone, > > I'm trying to automatically change message sends in my code, but I'm having trouble with compiled blocks. > For example, I want to change the message OrderedCollection new to OrderedCollection --> newTenured <-- in a specific method. I have the compiled block and the offset (26) for the message I want to change. However, searching for the selector new doesn't work because there can be multiple messages with the same name, and I only want to change the one at the given offset. > > theMethod > > | tmp1 | > 1 = tmp1 something: [ "rewrite this message send" OrderedCollection new ]. > tmp1 otherStruf: [ Dictionary new "do not rewrite this meesage send" ]. > ^ self > > > I can change the message when there is no block without any problem using the IR like this: > > transformMessageSend: compiledMethodOrBlock offset: offset > > | oldSelector newSelector irSendNode ir irSequences | > oldSelector := (compiledMethodOrBlock sourceNode sourceNodeForPC: offset) selector. > newSelector := self makeNewSelector: oldSelector. > > ir := compiledMethodOrBlock ir. > irSequences := ir allSequences flatCollect: #children. > irSendNode := (irSequences select: #isSend) detect: [ :e | e selector = oldSelector ]. > irSendNode selector: newSelector. > > ^ ir generate > selector: compiledMethodOrBlock selector; > yourself > > > But I get an error with ir generate when the compiledMethodOrBlock is a Block. If it's a normal compiled method, it works as expected. > Can anyone help me with this? Thanks! > > PS: I'm not forced to do it with the IR, ir can be done by using the AST. The only thing is that I'd like to avoid doing string manipulation > > Cheers and merry christmas, > Sebastian Jordan