Hello,
suppose you having a method: foo <primitive: ... > self recompileAndRetry a #recompileAndRetry should do following: 1) recompile method #foo and install new version of #foo into class 2) restart execution from callee of #foo, so that it will call the same method again (but its renewed version) This is similar to what debugger does, when you changing a method in code pane and accepting it, except that it restarting a context of called method, instead of restarting from a point where caller context did a message send (and so, if a new method contains a primitive, it will be called by VM). Any ideas, how i can do (2) easily? My own thoughts is following: recompileAndRetry | retryCtx retryMethod caller method rcvr | retryCtx := thisContext sender. caller := retryCtx sender. method := retryCtx method. "here we recompile a method, like following: " method := method methodClass recompile: method selector. "now we're resending the same message" args := Array new: method numArgs. 1 to: args size do: [ :i | args at: i put: (retryCtx tempAt: i) ]. thisContext terminateTo: caller. ^ retryCtx receiver perform: method selector arguments: args -- Best regards, Igor Stasenko AKA sig. |
On 11 April 2010 11:33, Igor Stasenko <[hidden email]> wrote:
> Hello, > > suppose you having a method: > > foo > <primitive: ... > > self recompileAndRetry > > > a #recompileAndRetry should do following: > 1) recompile method #foo and install new version of #foo into class > 2) restart execution from callee of #foo, so that it will call the > same method again (but its renewed version) > > > This is similar to what debugger does, when you changing a method in > code pane and accepting it, except that it restarting a > context of called method, instead of restarting from a point where > caller context did a message send (and so, if a new method contains a > primitive, > it will be called by VM). > > Any ideas, how i can do (2) easily? > > My own thoughts is following: > > recompileAndRetry > | retryCtx retryMethod caller method rcvr | > retryCtx := thisContext sender. > caller := retryCtx sender. > > method := retryCtx method. > "here we recompile a method, like following: " > method := method methodClass recompile: method selector. > > "now we're resending the same message" > args := Array new: method numArgs. > 1 to: args size do: [ :i | args at: i put: (retryCtx tempAt: i) ]. > > > thisContext terminateTo: caller. > ^ retryCtx receiver perform: method selector arguments: args > Forgot to add: the problem with the above, that if i restart it in that way, a call stack, when i enter the new #foo method will be following: caller context -> #recompileAndRetry context -> #foo while i want, obviously, a clean stack state, as if this method invoked naturally by interpreter: caller context -> #foo > > -- > Best regards, > Igor Stasenko AKA sig. > -- Best regards, Igor Stasenko AKA sig. |
In reply to this post by Igor Stasenko
On Sun, Apr 11, 2010 at 1:33 AM, Igor Stasenko <[hidden email]> wrote: Hello, One trick is to return the result of compileAndRetry, e.g. foo <primitive: ... > ^self recompileAndRetry
or e.g. foo
<primitive: ... error: error> (self shouldRecompileAndRetry: error) ifTrue: [^self recompileAndRetry]. self primitiveFailed
you then don't need to worry about munging the stack to get it right. You simply answer the result of tail-calling the primitive again at the end of recompileAndRetry. That's what VisualWorks does with FFI and user primitive calls that can fail because they're not yet linked. Searching for symbols in libraries and loading libraries is all done with image code invoked from e.g. ^self externalCallError: errorCode.
HTH Eliot
|
On 12 April 2010 21:28, Eliot Miranda <[hidden email]> wrote:
> > > On Sun, Apr 11, 2010 at 1:33 AM, Igor Stasenko <[hidden email]> wrote: >> >> Hello, >> >> suppose you having a method: >> >> foo >> <primitive: ... > >> self recompileAndRetry >> >> >> a #recompileAndRetry should do following: >> 1) recompile method #foo and install new version of #foo into class >> 2) restart execution from callee of #foo, so that it will call the >> same method again (but its renewed version) >> >> >> This is similar to what debugger does, when you changing a method in >> code pane and accepting it, except that it restarting a >> context of called method, instead of restarting from a point where >> caller context did a message send (and so, if a new method contains a >> primitive, >> it will be called by VM). >> >> Any ideas, how i can do (2) easily? > > One trick is to return the result of compileAndRetry, e.g. > foo > <primitive: ... > > ^self recompileAndRetry > or e.g. > foo > <primitive: ... error: error> > (self shouldRecompileAndRetry: error) ifTrue: > [^self recompileAndRetry]. > self primitiveFailed > > you then don't need to worry about munging the stack to get it right. You > simply answer the result of tail-calling the primitive again at the end of > recompileAndRetry. That's what VisualWorks does with FFI and user primitive > calls that can fail because they're not yet linked. Searching for symbols > in libraries and loading libraries is all done with image code invoked from > e.g. ^self externalCallError: errorCode. Thanks. That's what i actually came to myself: - loading library - loading library function - generating callout code - installing the code into a method - perform the method as a tail-call with same arguments I just was a little concerned that my method can't see its original caller (a context which originally made a call), so a method can't rely on a stack structure. > HTH > Eliot >> >> My own thoughts is following: >> >> recompileAndRetry >> | retryCtx retryMethod caller method rcvr | >> retryCtx := thisContext sender. >> caller := retryCtx sender. >> >> method := retryCtx method. >> "here we recompile a method, like following: " >> method := method methodClass recompile: method selector. >> >> "now we're resending the same message" >> args := Array new: method numArgs. >> 1 to: args size do: [ :i | args at: i put: (retryCtx tempAt: i) ]. >> >> >> thisContext terminateTo: caller. >> ^ retryCtx receiver perform: method selector arguments: args >> >> >> -- >> Best regards, >> Igor Stasenko AKA sig. >> > > > > > -- Best regards, Igor Stasenko AKA sig. |
Free forum by Nabble | Edit this page |