<div dir="ltr">Oops, I meant to say<div>    <span style="color:rgb(0,0,0);font-size:14px">This is &quot;trivial&quot; because in fact the VM is written in a subset of Smalltalk that is &quot;trivially&quot; translatable to C.</span></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Nov 18, 2015 at 4:32 PM, Eliot Miranda <span dir="ltr">&lt;<a href="mailto:eliot.miranda@gmail.com" target="_blank">eliot.miranda@gmail.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">Hi Ben,<div class="gmail_extra"><br><div class="gmail_quote"><span class="">On Wed, Nov 18, 2015 at 3:05 PM, Ben Coman <span dir="ltr">&lt;<a href="mailto:btc@openinworld.com" target="_blank">btc@openinworld.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><span><br>
On Thu, Nov 19, 2015 at 1:58 AM, Eliot Miranda &lt;<a href="mailto:eliot.miranda@gmail.com" target="_blank">eliot.miranda@gmail.com</a>&gt; wrote:<br>
&gt;<br>
&gt; On Tue, Nov 17, 2015 at 10:23 PM, Ryan Macnak &lt;<a href="mailto:rmacnak@gmail.com" target="_blank">rmacnak@gmail.com</a>&gt; wrote:<br>
&gt;&gt;<br>
&gt;&gt; This commit also broke the stack VMs, so something&#39;s probably amiss with the Slang changes.<br>
<br>
</span>I&#39;m not sure if a lightbulb just went on or my intuition misleads me.<br>
How does Slang related to the interpreter?<br>
i.e. Is it Slang that the interpreter interprets?<br></blockquote><div><br></div></span><div>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:</div><div><br></div><div><div>pushReceiverVariableBytecode</div><div><span style="white-space:pre-wrap">        </span>&lt;expandCases&gt;</div><div><span style="white-space:pre-wrap">        </span>self pushReceiverVariable: (currentBytecode bitAnd: 16rF).</div><div><span style="white-space:pre-wrap">        </span>self fetchNextBytecode</div></div><div><br></div><div><div>pushReceiverVariable: fieldIndex</div><div><br></div><div><span style="white-space:pre-wrap">        </span>self internalPush: (objectMemory fetchPointer: fieldIndex ofObject: self receiver).</div></div><div><br></div><div>All three implement their interpreter as a loop that indexes an Array of selectors for each byte code of methods like the above:</div><div><br></div><div><div>StackInterpreterSimulator&gt;&gt;run</div><div><span style="white-space:pre-wrap">        </span>&quot;Just run&quot;</div><div><span style="white-space:pre-wrap">        </span>quitBlock := [displayView ifNotNil:</div><div><span style="white-space:pre-wrap">                                </span>   [displayView containingWindow ifNotNil:</div><div><span style="white-space:pre-wrap">                                        </span>[:topWindow|</div><div><span style="white-space:pre-wrap">                                        </span>((World submorphs includes: topWindow)</div><div><span style="white-space:pre-wrap">                                        </span> and: [UIManager default confirm: &#39;close?&#39;]) ifTrue:</div><div><span style="white-space:pre-wrap">                                                </span>[topWindow delete]]].</div><div><span style="white-space:pre-wrap">                                </span>  ^self].</div><div><span style="white-space:pre-wrap">        </span>self initStackPages.</div><div><span style="white-space:pre-wrap">        </span>self loadInitialContext.</div><div><span style="white-space:pre-wrap">        </span>self internalizeIPandSP.</div><div><span style="white-space:pre-wrap">        </span>self fetchNextBytecode.</div><div><span style="white-space:pre-wrap">        </span>[true] whileTrue:</div><div><span style="white-space:pre-wrap">                </span>[self assertValidExecutionPointers.</div><div><span style="white-space:pre-wrap">                </span> atEachStepBlock value. &quot;N.B. may be nil&quot;</div><div><span style="white-space:pre-wrap">                </span> self dispatchOn: currentBytecode in: BytecodeTable.</div><div><span style="white-space:pre-wrap">                </span> self incrementByteCount].</div><div><span style="white-space:pre-wrap">        </span>localIP := localIP - 1.</div><div><span style="white-space:pre-wrap">        </span>&quot;undo the pre-increment of IP before returning&quot;</div><div><span style="white-space:pre-wrap">        </span>self externalizeIPandSP</div></div><div><br></div><div><div>dispatchOn: anInteger in: selectorArray</div><div><span style="white-space:pre-wrap">        </span>&quot;Simulate a case statement via selector table lookup.</div><div><span style="white-space:pre-wrap">        </span>The given integer must be between 0 and selectorArray size-1, inclusive.</div><div><span style="white-space:pre-wrap">        </span>For speed, no range test is done, since it is done by the at: operation.&quot;</div><div><br></div><div><span style="white-space:pre-wrap">        </span>self perform: (selectorArray at: (anInteger + 1)).</div></div><div><br></div><div>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.</div><div><br></div><div>This is fine for developing the VM but can&#39;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 &quot;trivial&quot; because in fact the VM is written in a subset of C that is &quot;trivially&quot; 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&#39;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.</div><div><br></div><div>Here&#39;s what the code of the interpreter loop looks like.  You&#39;ll be curious about the &lt;expandCases&gt; pragma above in pushReceiverVariableBytecode.  It and a couple of other pragmas are used to guide Slang in producing the interpreter loop&#39;s C code:</div><div><br></div><div>        /* begin internalizeIPandSP */</div><div>        localIP = pointerForOop(GIV(instructionPointer));</div><div>        localSP = pointerForOop(GIV(stackPointer));</div><div>        localFP = pointerForOop(GIV(framePointer));</div><div>        /* begin fetchNextBytecode */</div><div>        currentBytecode = byteAtPointer(++localIP);</div><div><br></div><div>        /* begin initExtensions */</div><div><br></div><div>        while (1) {</div><div>                bytecodeDispatchDebugHook();</div><div><br></div><div>                VM_LABEL(bytecodeDispatch);</div><div>                switch (currentBytecode) {</div><div>                case 0:</div><div>                        /* pushReceiverVariableBytecode */</div><div>                        {</div><div>                                VM_LABEL(pushReceiverVariableBytecode);</div><div>                                /* begin fetchNextBytecode */</div><div>                                currentBytecode = byteAtPointer(++localIP);</div><div><br></div><div>                                /* begin pushReceiverVariable: */</div><div>                                /* begin internalPush: */</div><div>                                longAtPointerput((localSP -= BytesPerOop), longAt(((longAt(localFP + FoxReceiver)) + BaseHeaderSize)));</div><div>                        }</div><div>                        break;</div><div>                case 1:</div><div>                        /* pushReceiverVariableBytecode */</div><div>                        {</div><div>                                VM_LABEL(pushReceiverVariableBytecode1);</div><div>                                /* begin fetchNextBytecode */</div><div>                                currentBytecode = byteAtPointer(++localIP);</div><div><br></div><div>                                /* begin pushReceiverVariable: */</div><div>                                /* begin internalPush: */</div><div>                                longAtPointerput((localSP -= BytesPerOop), longAt(((longAt(localFP + FoxReceiver)) + BaseHeaderSize) + 4 /* (currentBytecode bitAnd: 15) &lt;&lt; self shiftForWord */));</div><div>                        }</div><div>                        break;</div><div> </div><div>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.</div><div><br></div><div><br></div><div>And of course the Cogit is another story :-)</div><div><br></div></div><div><div dir="ltr"><div><span style="font-size:small;border-collapse:separate"><div>_,,,^..^,,,_<br></div><div>best, Eliot</div></span></div></div></div>
</div></div>
</blockquote></div><br><br clear="all"><div><br></div>-- <br><div class="gmail_signature"><div dir="ltr"><div><span style="font-size:small;border-collapse:separate"><div>_,,,^..^,,,_<br></div><div>best, Eliot</div></span></div></div></div>
</div>