Hi Stefan,<br><br><div class="gmail_quote">On Tue, Oct 16, 2012 at 12:11 PM, Stefan Marr <span dir="ltr">&lt;<a href="mailto:Stefan.Marr@vub.ac.be" target="_blank">Stefan.Marr@vub.ac.be</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Hi Eliot:<br>
<br>
May I ask you to give me a brief, high-level description of how the support for multiple bytecode sets works?<br></blockquote><div><br></div><div>sure.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Do you switch between different dispatch tables based on the method flag?<br>
Or do you extend the existing one and include the bit into the dispatch?<br></blockquote><div><br></div><div>This scheme is suggested by Claus Gittinger, and he uses something very similar in Smalltalk/X.  The idea is merely to include an offset that selects the bytecode set in the dispatch and set this offset on every send and return.  So with two bytecode sets there are 512 cases in the interpreter&#39;s dispatch loop and the offset is either 0 or 256.  In the Squeak VM this means code such as</div>
<div><br></div><div>StackInterpreter methods</div><div><div>fetchNextBytecode</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>&quot;This method fetches the next instruction (bytecode).&quot;</div><div>
<span class="Apple-tab-span" style="white-space:pre">        </span>currentBytecode := self fetchByte + bytecodeSetSelector</div></div><div><br></div><div><div>setMethod: aMethodObj</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>&quot;Set the method and determine the bytecode set based on the method header&#39;s sign.&quot;</div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span>&lt;inline: true&gt;</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>method := aMethodObj.</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>self assert: (objectMemory isOopCompiledMethod: method).</div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span>bytecodeSetSelector := (self methodUsesAlternateBytecodeSet: method)</div><div><span class="Apple-tab-span" style="white-space:pre">                                                        </span>ifTrue: [256]</div>
<div><span class="Apple-tab-span" style="white-space:pre">                                                        </span>ifFalse: [0]</div></div><div><br></div><div><div>methodUsesAlternateBytecodeSet: aMethodObj</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>&lt;api&gt;</div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span>&lt;inline: true&gt;</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>&quot;A negative header selects the alternate bytecode set.&quot;</div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span>^self headerIndicatesAlternateBytecodeSet: (self headerOf: aMethodObj)</div></div><div><br></div><div><div>headerIndicatesAlternateBytecodeSet: methodHeader</div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span>&quot;A negative header selects the alternate bytecode set.&quot;</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>^(objectMemory integerValueOf: methodHeader) &lt; 0</div>
</div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Do you have any performance numbers, or pointers to literature?<br></blockquote><div><br></div><div>
I couldn&#39;t see much of an impact when I measured it, but I don&#39;t have my measurements handy.  Modern processors cache the read so well that even in the interpreter impact is minimal (it was certainly less than 10%, probably less than 5%, in a pure interpreter), and of course in the JIT it matters not at all.  But the impact was enough that I ended up conditionalizing the code so it reads</div>
<div><br></div><div><div>fetchNextBytecode</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>&quot;This method fetches the next instruction (bytecode). Each bytecode method is responsible for fetching the next bytecode, preferably as early as possible to allow the memory system time to process the request before the next dispatch.&quot;</div>
<div><br></div><div><span class="Apple-tab-span" style="white-space:pre">        </span>self cppIf: MULTIPLEBYTECODESETS</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>ifTrue: [currentBytecode := self fetchByte + bytecodeSetSelector]</div>
<div><span class="Apple-tab-span" style="white-space:pre">                </span>ifFalse: [currentBytecode := self fetchByte]</div></div><div><br></div><div>That was easier than trying to define bytecodeSetSelector as 0, e.g. via a macro.</div>
<div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">I found hints to Smalltalk/X, VisualAgeJava/Smalltalk, and I think MagLev/Gemstone might also use that kind of technique.<br>

But, unfortunately, Google is a bit shy about papers, or interesting references.<br></blockquote><div><br></div><div>I don&#39;t suppose its something people do a lot.  Claus&#39; VM is the only one I was aware of.  I think its useful to support multiple languages and to support migrating the bytecode set using incremental development, but in a production VM if one didn&#39;t need the support I think one would end up disabling it.</div>
<div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Thanks a lot<br>
<span class="HOEnZb"><font color="#888888">Stefan<br></font></span></blockquote></div><div><br></div>-- <br>cheers,<div>Eliot</div><br>