[Spy] How to inject code *inside* a method
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? Thanks in advance, R
You could probably solve that with aspects. There was some talk about an aspect project a while ago but I forgot what it was called. On 06.12.2013, at 10:00, Roberto Minelli <roberto.minelli@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?
Thanks in advance, R
Hi Roberto, usually what you need is support for so called ABIA (Around, Begin, Inner and After) execution. Brings Smallscript back to my brain which had nice support for this. In Squeak there was AspectS, I dont know if there is a port of AspectS for Pharo. Maybe the PHANtom project can be of help here as it claims to be a modern aspect language for Pharo: http://de.slideshare.net/esug/phantom-a-modern-aspect-language-for-pharo Hope this helps Bye T.
Gesendet: Freitag, 06. Dezember 2013 um 10:00 Uhr Von: "Roberto Minelli" <roberto.minelli@usi.ch> An: Pharo-dev <pharo-dev@lists.pharo.org> Betreff: [Pharo-dev] [Spy] How to inject code *inside* a method
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?
Thanks in advance, R
I also think you should have a look at Phantom :) Maybe Johan will give you more details :) Ben On 06 Dec 2013, at 10:14, Torsten Bergmann <astares@gmx.de> wrote:
Hi Roberto,
usually what you need is support for so called ABIA (Around, Begin, Inner and After) execution. Brings Smallscript back to my brain which had nice support for this.
In Squeak there was AspectS, I dont know if there is a port of AspectS for Pharo.
Maybe the PHANtom project can be of help here as it claims to be a modern aspect language for Pharo:
http://de.slideshare.net/esug/phantom-a-modern-aspect-language-for-pharo
Hope this helps
Bye T.
Gesendet: Freitag, 06. Dezember 2013 um 10:00 Uhr Von: "Roberto Minelli" <roberto.minelli@usi.ch> An: Pharo-dev <pharo-dev@lists.pharo.org> Betreff: [Pharo-dev] [Spy] How to inject code *inside* a method
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?
Thanks in advance, R
On 06 Dec 2013, at 10:01, Roberto Minelli <roberto.minelli@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?
Sadly not yet⦠we plan to have real support for this in Pharo4. The AOP solutions (both AspectS and Phantom) do *not* support point cuts on sub-method concepts like âinstance variable accessâ. The stuff I did for my PhD supports this quite nicely⦠but that I have not yet ported to Pharo. (The idea is to do an âengineering gradeâ pass over this and put it in Pharo not as a research prototype but as a real, production ready concept). I really need to push this⦠people need it. There is a way to do all this on a lower level (e.g. AST transformation or IR transformation)⦠I will write a mail how to do that later the weekend. Marcus
WOW.. Thank you guys for such answers!! It seems this is an hot topic. However, now I will try to hack something on top of Spy and look at Phantom in the weekend ;) Cheers, R On Dec 6, 2013, at 10:35 AM, Marcus Denker <marcus.denker@inria.fr> wrote:
On 06 Dec 2013, at 10:01, Roberto Minelli <roberto.minelli@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?
Sadly not yet⦠we plan to have real support for this in Pharo4.
The AOP solutions (both AspectS and Phantom) do *not* support point cuts on sub-method concepts like âinstance variable accessâ.
The stuff I did for my PhD supports this quite nicely⦠but that I have not yet ported to Pharo. (The idea is to do an âengineering gradeâ pass over this and put it in Pharo not as a research prototype but as a real, production ready concept).
I really need to push this⦠people need it.
There is a way to do all this on a lower level (e.g. AST transformation or IR transformation)⦠I will write a mail how to do that later the weekend.
Marcus
On 06 Dec 2013, at 10:51, Roberto Minelli <roberto.minelli@usi.ch> wrote:
WOW.. Thank you guys for such answers!! It seems this is an hot topic.
However, now I will try to hack something on top of Spy and look at Phantom in the weekend ;)
Phantom does *not* support sub-method elements. Marcus
On 06 Dec 2013, at 10:01, Roberto Minelli <roberto.minelli@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.
â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.
I love this in 5 lines!!!!
Me, too! :) Doru On Fri, Dec 6, 2013 at 9:38 PM, Stéphane Ducasse <stephane.ducasse@inria.fr>wrote:
â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.
I love this in 5 lines!!!!
-- www.tudorgirba.com "Every thing has its own flow"
Hi Roberto, Unfortunately injecting code in the middle of a method is not supported by Spy. Bifrost does this (http://scg.unibe.ch/research/bifrost). However it may not properly work on Pharo 3. Alexandre -- _,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;: Alexandre Bergel http://www.bergel.eu ^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;. On Dec 6, 2013, at 6:00 AM, Roberto Minelli <roberto.minelli@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?
Thanks in advance, R
On 06 Dec 2013, at 15:46, Alexandre Bergel <alexandre.bergel@me.com> wrote:
Hi Roberto,
Unfortunately injecting code in the middle of a method is not supported by Spy. Bifrost does this (http://scg.unibe.ch/research/bifrost). However it may not properly work on Pharo 3.
The real solution is to get the meta links (Reflectivity, which is the underlying basis of bifrost, too), to work *for real* and use if for everything. Marcus
participants (8)
-
Alexandre Bergel -
Benjamin -
Marcus Denker -
Max Leske -
Roberto Minelli -
Stéphane Ducasse -
Torsten Bergmann -
Tudor Girba