["BUG"][FIX?]Incorrect Pseudo-Codefor#whileTrue:/#whileFalse:?

Mark van Gulik ghoul6 at home.net
Mon Jan 8 01:50:31 UTC 2001


Your explanations are exactly correct.  I haven't looked at the Squeak VM in
a while, but I'm pretty sure it caches the pc in a local variable (which is
typically just a register when compiled on modern hardware).  The actual pc
slot in the context is only written to when a non-primitive call is made.
Since #realPc is non-primitive but #pc counts as a primitive (because it's
marked as quick-return instVar #1), the actual value of "thisContext pc"
returns the pc value that was most recently written back to the context.
Since no non-primitive methods had been invoked at that point, the pc simply
pointed to the first instruction of the block.  If a non-primitive method
*had* been invoked before the call to #pc, the #pc method would have
answered the position of the instruction after that call.  Phew.

Of course, this optimization doesn't affect things like exception handling,
because by the time you're actually examining/manipulating some context,
you've already left that context (i.e., you're inside a called method).  The
debugger simulation is similar, in that the code simulating an instruction
occurs several call levels past the context that has been suspended (and is
being simulated).  The pc and stackp of such a context is guaranteed correct
at that time.


on 1/7/01 1:09 PM, Stephan Rudlof at sr at evolgo.de wrote:
> Dear Bob and Mark,
> 
> first I want to thank you for your interesting contributions!
> 
> After some playing with the debugger I think I have understood some of the
> tricky issues.
> But I prefer to prove my understanding:
> 
> Does
>>> !BlockContext methodsFor: 'controlling' stamp: 'RAA 1/5/2001 23:10'!
>>> repeatEndlessly
>>> | loopAgain |
>>> "Evaluate the receiver repeatedly, ending only if the block explicitly
>>> returns."
>>> 
>>> loopAgain _ thisContext pc.
>>> self value.
>>> thisContext jumpTo: loopAgain stack: 1.
>>> self halt.
>>> ! !
> 
> changed to
> ---
> BlockContext>>
> repeatEndlessly
> | loopAgain |
> "Evaluate the receiver repeatedly, ending only if the block
> explicitly returns."
> 
> loopAgain _ thisContext realPc.
> self value.
> thisContext jumpTo: loopAgain.
> self halt.
> ---
> as bytecodes
> ---
> 17 <89> pushThisContext:
> 18 <D0> send: realPc
> 19 <68> popIntoTemp: 0
> 20 <70> self
> 21 <C9> send: value
> 22 <87> pop
> 23 <89> pushThisContext:
> 24 <10> pushTemp: 0
> 25 <E1> send: jumpTo:
> 26 <87> pop
> 27 <70> self
> 28 <D2> send: halt
> 29 <87> pop
> 30 <78> returnSelf
> ---
> work now, since #jumpTo: as bytecodes
> ---
> 5 <10> pushTemp: 0
> 6 <81 01> storeIntoRcvr: 1
> 8 <7C> returnTop
> ---
> results in moving loopAgain to the stack, what is expected by bytecode 19 in
> #repeatEndlessly and results in assigning it to loopAgain again?
> I know that it works, but I want to be sure that my explanation is
> correct...
> 
> <snipped>
> 
> Given
> ---
> BlockContext>>
> repeatEndlesslyDangerous
> | loopAgain |
> "Evaluate the receiver repeatedly, ending only if the block
> explicitly returns."
> 
> loopAgain _ thisContext pc.
> self value.
> thisContext jumpTo: loopAgain.
> self halt.
> ---
> and
> ---
> BlockContext>>
> whileTrue4Dangerous: aBlock
> 
> "
> | x |
> x _ 0.
> [(x _ x + 1) < 100] whileTrue4Dangerous: [Transcript show: x printString;
> cr].
> "
> [
> self value ifFalse: [^self].
> aBlock value.
> ] repeatEndlesslyDangerous
> ---
> crashes if called by
> ---
> | x |
> self halt.
> x _ 0.
> [(x _ x + 1) < 100] whileTrue4Dangerous: [Transcript show: x printString;
> cr].
> ---
> with 'proceed'ing at the 'halt'.
> 
> But going into the debugger there carefully followed by 'step's and 'send's
> with 'proceed'ing in
> ---
> repeatEndlesslyDangerous
> | loopAgain |
> "Evaluate the receiver repeatedly, ending only if the block
> explicitly returns."
> 
> loopAgain _ thisContext pc.
> "proceed here with 'value' highlighted"        self value.
> thisContext jumpTo: loopAgain.
> self halt.
> ---
> at marked statement works.
> 
> Explanation: The VM takes an earlier bytecode for loopAgain as the debugger,
> which results in a stack overflow by pushing thisContext (followed by
> sending pc) again and again.
> Is this correct?
> 
> 
> Greetings,
> 
> Stephan





More information about the Squeak-dev mailing list