[Pharo-dev] [Spy] How to inject code *inside* a method

Marcus Denker marcus.denker at inria.fr
Fri Dec 6 04:58:55 EST 2013


On 06 Dec 2013, at 10:01, Roberto Minelli <roberto.minelli at usi.ch> wrote:

> Hi guys,
> 
> I am using Spy for my project, and I need to do something which, on top of my knowledge, is not supported.
> 
> Here is the point: Spy allows to insert code before (#beforeRun:with:in:) and after (#afterRun:with:in:) and works perfectly.
> 
> Now suppose I want to inject some code *inside* the method, e.g.,
> 
> aMethodToBeProfiled
> 
> 	do something
> 
> 	"Injected code accessing some fields of the current instance of this object”
> 	Transcript show: self field asString.
> 
> Is there any support for this?
> 

Here is how to do it on the IR level:

A class TestMy with

test
	^x + 1 + x

byte code is:

13 <00> pushRcvr: 0
14 <76> pushConstant: 1
15 <B0> send: +
16 <00> pushRcvr: 0
17 <B0> send: +
18 <7C> returnTop




“get a copy of the IR tree"
irMethod := (TestMy>>#test) ir copy.

“get all instance variable access IR instructions”
allIvarAccesses :=  irMethod allInstructionsMatching: [ :ir |ir isInstVarAccess].

“insert code for “1 halt” before all of them"
allIvarAccesses do: [ :each | each  addInstructionsBefore: {  IRInstruction pushLiteral: 1.  IRInstruction send:  #halt. IRInstruction popTop }].

“generate a new compiledMethod"
cm := irMethod generate:  (TestMy>>#test) trailer.

“install in the class"
TestMy addSelector: #test withMethod: cm.

17 <76> pushConstant: 1
18 <D0> send: halt
19 <87> pop
20 <00> pushRcvr: 0
21 <76> pushConstant: 1
22 <B0> send: +
23 <76> pushConstant: 1
24 <D0> send: halt
25 <87> pop
26 <00> pushRcvr: 0
27 <B0> send: +
28 <7C> returnTop


—> TestMy new test

What is now yet wiring is quick return methods —> need to clear the primitive in that case, should not be hard to do.






More information about the Pharo-dev mailing list