[Vm-dev] An event driven Squeak VM
Andreas Raab
andreas.raab at gmx.de
Tue Dec 8 08:38:30 UTC 2009
Hi Ang -
I haven't completed the work. At this point I've been able to run the
VM, execute a blocking FFI call (MessageBox, OpenFile) have the VM run
happily in the background until I hit OK in the dialog. When the VM
should return from the callback, it violently crashes :( There is some
state that isn't preserved correctly but it's hard to find these things.
I'll keep folks informed how this unfolds.
Cheers,
- Andreas
Ang BeePeng wrote:
>
>
> Hi,
>
> I'd like to make my interpreter run until there's no more work to do, and
> return. I'm not good enough to put things that you explained into coding.
> Can you show or lead me to get it work?
>
> Or, maybe, can you share the source of event-driven Squeak VM, so that I can
> learn from the code?
>
> Thanks.
>
> Ang Beepeng
>
>
> Andreas Raab wrote:
>>
>> having interpret() run until "there is
>> no more work to do" and return from interpret() when it's all said and
>> done. The trick is that instead of running the idle loop, the VM would
>> determine that it has no more work to do when there is no runnable
>> process, so when it finds that there is no runnable process it would
>> return from interpret saying "my work's done here, there is no more code
>> to run at this point, ask me again when an external event comes in".
>>
>> The changes would be fairly straight forward: First, nuke the idle loop
>> and allow wakeHighestPriority to return nil when there's no runnable
>> process. Second, have transferTo: do a longjmp to the registered
>> vmExitBuf to leave interpret(). Third, have interpret register the
>> vmExitBuf and wake up the highest priorty process like here:
>>
>> interpret
>> "install jmpbuf for main interpreter"
>> (self setjmp: vmExitBuf) == 0 ifTrue:[
>> self checkForInterrupts. "timers etc"
>> "transferTo: longjmps if arg is nil so no need to check"
>> self transferTo: self wakeHighestPriority.
>>
>> "this is the current interpret() implementation"
>> self internalizeIPandSP.
>> self fetchNextBytecode.
>> [true] whileTrue: [self dispatchOn: currentBytecode in: BytecodeTable].
>>
>> ].
>>
>> At this point we can write a client loop that effectively looks like:
>>
>> /* run the interpreter */
>> while(!done) {
>> /* check for new events */
>> ioProcessEvents();
>> /* run processes resulting from the events */
>> interpret();
>> }
>>
>> Now, obviously this is inefficient, we'd want to replace the
>> ioProcessEvents() call with something more elaborate that reacts to the
>> incoming OS events, takes the next scheduled delay into account, checks
>> for socket handles etc. But I'm sure you're getting the idea. Instead of
>> wasting our time in the idleProcess, we just return when there's no more
>> work to do and it's up to the caller to run interpret() as often or as
>> rarely as desired.
>>
>> I also think that this scheme could be made backwards compatible by
>> ensuring that we never call interpret() recursively. In this case an
>> "old" image with the idle process would run the way it does today, and a
>> "new" image without the idle process would live in the shiny new event
>> driven world and return as needed.
>>
>> What do you think? Any reasons why this wouldn't work?
>>
>> Cheers,
>> - Andreas
>>
>>
>>
>
More information about the Vm-dev
mailing list