Context >> #quickStep broken on non-local returns?

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

Context >> #quickStep broken on non-local returns?

cmfcmf
Hi,

I am playing around with the simulator (e.g., Context class >> #trace:). To
make the simulation faster, I'd like to quick-step some message sends.
However, I noticed that quick-stepping doesn't work as intended if a
quick-stepped send executes a non-local return.

Given the following method:



Running this method in the simulator using repeated calls to Context >>
#step for all non-send-bytecodes and Context >> #quickStep for all send
bytecodes works fine except when quick-stepping the send of at:ifPresent:
The context returned by quickstepping this send has an empty stack, whereas
I would expect the return value of 84 on top of the stack.

The root cause, as far as I can see, is Context >>
#quickSend:to:with:lookupIn:, which seems to make assumptions in its
ifCurtailed: block that appear to not (or no longer) hold true. [1]

I have attached a ContextTest class that includes the example method shown
above and a failing test.

Note that the debugger does _not_ appear to use the Context >> #quickStep
mechanism when using the "over" button (in fact, the quickStep method does
not appear to be used at all). The debugger uses a different technique,
namely Context >> #runUntilErrorOrReturnFrom: (Debugger >> #doStep ->
Process >> #completeStep: -> Process >> #complete: -> Context >>
#runUntilErrorOrReturnFrom:).

I observed the behavior in a fresh Squeak 5.3 image.

Best
Christian

ContextTest.st <http://forum.world.st/file/t372201/ContextTest.st>  

[1] Below, I have annotated the ifCurtailed: block of Context >>
#quickSend:to:with:lookupIn: with my understanding of what it is trying to
do and where it goes wrong:


------

I have already tried some things to fix the ifCurtailed: block in Context >>
#quickSend:to:with:lookupIn:, but I'm not sure if that's entirely correct
either. However, it at least passes the test.





--
Sent from: http://forum.world.st/Squeak-Dev-f45488.html

Reply | Threaded
Open this post in threaded view
|

Re: Context >> #quickStep broken on non-local returns?

cmfcmf
I'm afraid the code was lost from my message, even though the preview here on
the forum included the code :( (Possibly I shouldn't have wrapped it in
"raw" tags [using the More -> Raw Text button of the editor here on the
forum]?) Anyways, here's the code again:

... snip ...

Given the following method:

methodToUseForQuickStepping
        | dictionary |
        dictionary := Dictionary new.
        dictionary at: #foo put: 42.
        dictionary at: #foo ifPresent: [:value | ^ value * 2].
        ^ nil


... snip ...


[1] Below, I have annotated the ifCurtailed: block of Context >>
#quickSend:to:with:lookupIn: with my understanding of what it is trying to
do and where it goes wrong:

"This is supposed to be the block context, i.e. the context of the block
passed to at:ifPresent:, that just executed the non-local return. However,
it is _not_ (bug)"
contextToReturnTo := thisContext sender receiver.

"Now, given the block context, decrement the pc so that we are right
before/at(?) the bytecode that caused the non-local return"
contextToReturnTo pc: contextToReturnTo previousPc.

"If it is indeed a non-local return (when would it not be??)"
contextToReturnTo willReturnTopFromMethod ifTrue:
        "push the return value onto the stack (tempAt: 1 is the result temporary of
the BlockClosure >> ifCurtailed: method"
        [contextToReturnTo push: (thisContext sender tempAt: 1)].

"Completely unrelated to everything above, escape the handling of
ifCurtailed blocks by setting my sender to the sender of
#quickSend:to:with:lookupIn:"
thisContext swapSender: thisContext home sender.
"This is the value that will be returned from #quickSend:to:with:lookupIn:"
contextToReturnTo]
------

I have already tried some things to fix the ifCurtailed: block in Context >>
#quickSend:to:with:lookupIn:, but I'm not sure if that's entirely correct
either. However, it at least passes the test.

contextToReturnTo := thisContext receiver sender. "block / method that was
returned into"
contextToReturnTo push: (thisContext sender tempAt: 1) "return value".
thisContext swapSender: thisContext home sender. "Make this block return to
the method's sender"
contextToReturnTo]



--
Sent from: http://forum.world.st/Squeak-Dev-f45488.html