[Vm-dev] VM Maker: VMMaker.oscog-eem.1522.mcz

Eliot Miranda eliot.miranda at gmail.com
Thu Nov 19 00:33:49 UTC 2015


Oops, I meant to say
    This is "trivial" because in fact the VM is written in a subset of
Smalltalk that is "trivially" translatable to C.

On Wed, Nov 18, 2015 at 4:32 PM, Eliot Miranda <eliot.miranda at gmail.com>
wrote:

> Hi Ben,
>
> On Wed, Nov 18, 2015 at 3:05 PM, Ben Coman <btc at openinworld.com> wrote:
>
>>
>> On Thu, Nov 19, 2015 at 1:58 AM, Eliot Miranda <eliot.miranda at gmail.com>
>> wrote:
>> >
>> > On Tue, Nov 17, 2015 at 10:23 PM, Ryan Macnak <rmacnak at gmail.com>
>> wrote:
>> >>
>> >> This commit also broke the stack VMs, so something's probably amiss
>> with the Slang changes.
>>
>> I'm not sure if a lightbulb just went on or my intuition misleads me.
>> How does Slang related to the interpreter?
>> i.e. Is it Slang that the interpreter interprets?
>>
>
> The VM is written as a Smalltalk program.  There are three different
> versions of the interpreter in it, Interpreter, which is a classical
> blue-book interpreter that uses context objects to represent method
> activations, the STackInterpreter that avoids creating contexts as much as
> possible and uses stack frames to represent method activations, and
> CoInterpreter, a subclass of StackInterpreter that can interoperate with
> the JIT so that machine code can execute Smalltalk on its own, interleaved
> with the CoInterpreter interpreting methods that have yet to be fitted or
> are judged too big to be worth jitting.  All of these interpreters
> interpret Smalltalk bytecocde methods.  They contain methods like the
> following, which is the pushInstVar byte code used to push an instance
> variable of the receiver onto the stack:
>
> pushReceiverVariableBytecode
> <expandCases>
> self pushReceiverVariable: (currentBytecode bitAnd: 16rF).
> self fetchNextBytecode
>
> pushReceiverVariable: fieldIndex
>
> self internalPush: (objectMemory fetchPointer: fieldIndex ofObject: self
> receiver).
>
> All three implement their interpreter as a loop that indexes an Array of
> selectors for each byte code of methods like the above:
>
> StackInterpreterSimulator>>run
> "Just run"
> quitBlock := [displayView ifNotNil:
>   [displayView containingWindow ifNotNil:
> [:topWindow|
> ((World submorphs includes: topWindow)
> and: [UIManager default confirm: 'close?']) ifTrue:
> [topWindow delete]]].
>  ^self].
> self initStackPages.
> self loadInitialContext.
> self internalizeIPandSP.
> self fetchNextBytecode.
> [true] whileTrue:
> [self assertValidExecutionPointers.
> atEachStepBlock value. "N.B. may be nil"
> self dispatchOn: currentBytecode in: BytecodeTable.
> self incrementByteCount].
> localIP := localIP - 1.
> "undo the pre-increment of IP before returning"
> self externalizeIPandSP
>
> dispatchOn: anInteger in: selectorArray
> "Simulate a case statement via selector table lookup.
> The given integer must be between 0 and selectorArray size-1, inclusive.
> For speed, no range test is done, since it is done by the at: operation."
>
> self perform: (selectorArray at: (anInteger + 1)).
>
> The BytecodeTable has 256 entries.  Depending on the byte code set the
> first 16 elements might be #pushReceiverVariableBytecode, the next 16
> #pushTemporaryVariableBytecode and so on.
>
> This is fine for developing the VM but can't yield useful performance in
> practice.  We need somehow to translate the Smalltalk code into something a
> real machine can run.  We do this in two steps.  First, the Smalltalk code
> is converted from Smalltalk to C.  This is "trivial" because in fact the VM
> is written in a subset of C that is "trivially" translatable to C.  There
> are no Dictionaries or Sets in the bowels of the VM, just whole and for
> looks and performs mapped either to inlining of code or to calling through
> function pointers.  The thing that does the Smalltalk to C translation is
> called Slang.  The pours trees of the methods of the VM are translated into
> Slang's parse trees which in turn implement analysis and output code that
> allows the entire VM to be written out as a C program.  The last step is to
> compile this using a common or garden C compiler.
>
> Here's what the code of the interpreter loop looks like.  You'll be
> curious about the <expandCases> pragma above in
> pushReceiverVariableBytecode.  It and a couple of other pragmas are used to
> guide Slang in producing the interpreter loop's C code:
>
>         /* begin internalizeIPandSP */
>         localIP = pointerForOop(GIV(instructionPointer));
>         localSP = pointerForOop(GIV(stackPointer));
>         localFP = pointerForOop(GIV(framePointer));
>         /* begin fetchNextBytecode */
>         currentBytecode = byteAtPointer(++localIP);
>
>         /* begin initExtensions */
>
>         while (1) {
>                 bytecodeDispatchDebugHook();
>
>                 VM_LABEL(bytecodeDispatch);
>                 switch (currentBytecode) {
>                 case 0:
>                         /* pushReceiverVariableBytecode */
>                         {
>                                 VM_LABEL(pushReceiverVariableBytecode);
>                                 /* begin fetchNextBytecode */
>                                 currentBytecode = byteAtPointer(++localIP);
>
>                                 /* begin pushReceiverVariable: */
>                                 /* begin internalPush: */
>                                 longAtPointerput((localSP -= BytesPerOop),
> longAt(((longAt(localFP + FoxReceiver)) + BaseHeaderSize)));
>                         }
>                         break;
>                 case 1:
>                         /* pushReceiverVariableBytecode */
>                         {
>                                 VM_LABEL(pushReceiverVariableBytecode1);
>                                 /* begin fetchNextBytecode */
>                                 currentBytecode = byteAtPointer(++localIP);
>
>                                 /* begin pushReceiverVariable: */
>                                 /* begin internalPush: */
>                                 longAtPointerput((localSP -= BytesPerOop),
> longAt(((longAt(localFP + FoxReceiver)) + BaseHeaderSize) + 4 /*
> (currentBytecode bitAnd: 15) << self shiftForWord */));
>                         }
>                         break;
>
> So we get to develop the VM in Smalltalk, but the code is reasonably well
> compiled by a C compiler and hence acceptably efficiently executed by a
> commodity microprocessor.
>
>
> And of course the Cogit is another story :-)
>
> _,,,^..^,,,_
> best, Eliot
>



-- 
_,,,^..^,,,_
best, Eliot
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.squeakfoundation.org/pipermail/vm-dev/attachments/20151118/7b10dff8/attachment-0001.htm


More information about the Vm-dev mailing list