[Vm-dev] Question about process preemption during longJump

Eliot Miranda eliot.miranda at gmail.com
Tue Apr 16 18:12:46 UTC 2013


Hi Guillermo,

On Tue, Apr 16, 2013 at 8:27 AM, Guillermo Polito <guillermopolito at gmail.com
> wrote:

>
> Hi! I'm looking at some code from StackInterpreter, and the given piece of
> code raised a question I cannot fully answer:
>
> longUnconditionalJump
> | offset |
>  offset := (((currentBytecode bitAnd: 7) - 4) * 256) + self fetchByte.
> localIP := localIP + offset.
> (offset < 0 "backward jump means we're in a loop; check for possible
> interrupts"
>  and: [*localSP < stackLimit*]) ifTrue:
> [self externalizeIPandSP.
>  self checkForEventsMayContextSwitch: true.
>  self browserPluginReturnIfNeeded.
>  self internalizeIPandSP].
> self fetchNextBytecode
>
> What does the (localSP < stackLimit) condition stand for? What is its
> intention when deciding to make (or not) a context switch?
>

The Cog and Stack VMs steal a technique from Peter Deutsch's PS and HPS VMs
which combines the stack page overflow check on method entry with the check
for events.  Internally these VMs run Smalltalk on a small set of stack
pages (this is to do with going fast by using a call-instruction-based
inline cache, and needing to implement contexts, mapping stack frames to
contexts as needed).  Periodically the VM needs to break out of executing
Smalltalk and check for events (the VMs heartbeat)., and this is done by
setting the stackLimit to the highest possible value ((all ones) so that
all stack overflow checks fail, and on the next method entry or backward
jump the VM will check for stack overflow.  If there really is a stack
overflow then it is dealt with, but if the stack limit has been changed to
all ones then the  M checks for events.

This is explained here:
http://www.mirandabanda.org/cogblog/2009/01/14/under-cover-contexts-and-the-big-frame-up/

"We have a linked list of StackPage objects, one for each page, that we use
to keep stack pages in order of usage, along with free pages, referenced by
a variable called the mostRecentlyUsedPage. Each StackPage keeps track of
whether a stack page is in use (baseFP is non-null) and what part of the
page is in use (from the first slot through to the headSP) and what the
frames are in the page (the list from headFP chained through caller saved
fp to the baseFP). The interpreter’s current stack page is called
stackPage. On stack switch we load stackLimit from stackPage’s stackLimit.
Peter cleverly realised that one can use the stackLimit check to cause the
VM to break out of execution to process input events. The VM is set up to
respond to potential input with an interrupt handler that sets the
stackLimit to all ones (the highest possible address) so that the next
stack overflow check will fail. We also check for stack overflow on
backward branch so that we can break out of infinite loops:

*StackInterpreter methods for jump bytecodes*
*longUnconditionalJump*
        | offset |
        offset *:=* (((currentBytecode bitAnd: 7) - 4) * 256) + self
fetchByte.
        localIP *:=* localIP + offset.
        (offset < 0 “backward jump means we’re in a loop; check for
possible interrupts”
         and: [localSP < stackLimit]) ifTrue:
                 [self externalizeIPandSP.
                  self checkForEventsMayContextSwitch: true.
                  self browserPluginReturnIfNeeded.
                  self internalizeIPandSP].
        self fetchNextBytecode
"

-- 
cheers,
Eliot
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.squeakfoundation.org/pipermail/vm-dev/attachments/20130416/c282c5f4/attachment.htm


More information about the Vm-dev mailing list