<div dir="ltr">&gt; Hi Ralph,<br>&gt; <br>&gt; On Sun, Nov 2, 2014 at 9:48 PM, Ralph Boland &lt;<a href="mailto:rpboland@gmail.com">rpboland@gmail.com</a>&gt; wrote:<br>&gt; <br>&gt; &gt;<br>&gt; &gt; &gt;&gt;<br>&gt; &gt; &gt;&gt; I am working on a parser generator tool (a replacement for SmaCC) and<br>&gt; &gt; &gt;&gt; one of the things I a m interested in is the direct translation of<br>&gt; &gt; &gt;&gt; language specifications into the virtual machine code (SmaCC and my<br>&gt; &gt; &gt;&gt; current version of it use Squeak as the target language).<br>&gt; &gt; &gt;&gt;<br>&gt; &gt;<br>&gt; &gt; &gt; First, a different approach than compiling to Smalltalk is to compile to<br>&gt; &gt; a<br>&gt; &gt; &gt; parse tree.  We do this in the pseudo JavaScript compiler we&#39;ve<br>&gt; &gt; implemented<br>&gt; &gt; &gt; at Cadence, translating an AST into a Squeak compiler parse tree for code<br>&gt; &gt; &gt; generation.  Targeting a parse tree gives you much more freedom; you can<br>&gt; &gt; &gt; express things that aren&#39;t expressible in Smalltalk.  And if you target<br>&gt; &gt; &gt; bytecodes you can do even more.<br>&gt; &gt;<br>&gt; &gt;<br>&gt; &gt; I never considered using a parse tree as the target.  An interesting idea<br>&gt; &gt; which in many instances may be the best approach.  But for my regular<br>&gt; &gt; expression<br>&gt; &gt; example I would still want to generate byte codes.  In any case I wouldn&#39;t<br>&gt; &gt; want to<br>&gt; &gt; restrict users of my parser generator tool to any one of the three options<br>&gt; &gt; (Smalltalk code,<br>&gt; &gt; parse tree, byte code).  It is my responsibility to make all three options<br>&gt; &gt; as easy and<br>&gt; &gt; efficient as reasonably possible for users of the parser generator tool.<br>&gt; &gt; Haven&#39;t put<br>&gt; &gt; much thought into this yet though.   So far Smalltalk (Squeak) is the only<br>&gt; &gt; option.<br>&gt; &gt;<br>&gt; &gt;<br>&gt; &gt; &gt;&gt; One of the problems I have is that, for some languages, the natural<br>&gt; &gt; &gt;&gt; translation<br>&gt; &gt; &gt;&gt; into VM code uses computed gotos.<br>&gt; &gt; &gt;&gt; There are two scenarios here:<br>&gt; &gt; &gt;&gt;<br>&gt; &gt; &gt;&gt;      1) goto X  where X is a variable.<br>&gt; &gt; &gt;&gt;      2) goto  (coll at: y)  where coll is a Collection.<br>&gt; &gt; &gt;&gt;<br>&gt; &gt;<br>&gt; &gt; &gt; There are several ways of implementing this without computed bytecodes in<br>&gt; &gt; &gt; the instruction set, but there is also the possibility of implementing it<br>&gt; &gt; &gt; directly in the instruction set.<br>&gt; &gt;<br>&gt; &gt; &gt; Off the top of my head one could<br>&gt; &gt;<br>&gt; &gt; &gt; - map to perform: using some mangled selector.  Yes this is problematic<br>&gt; &gt; &gt; because one has to split the scope between the two methods, so in general<br>&gt; &gt; &gt; it&#39;s not a solution<br>&gt; &gt;<br>&gt; &gt; Doesn&#39;t appeal to me.<br>&gt; &gt;<br>&gt; &gt; &gt; - map to a case statement, which is what Squeak does. Just map it to a<br>&gt; &gt; &gt; sequence of compare and branches.  Or better still, to a binary tree.<br>&gt; &gt; &gt; Coincidentally this is used by the JIT to implement block dispatch in<br>&gt; &gt; &gt; methods that contain more than one block.  I know of other VM<br>&gt; &gt; &gt; implementations using it for PIC dispatch with really good performance.<br>&gt; &gt;<br>&gt; &gt; I don&#39;t know what you mean my Squeak mapping to a case statement since<br>&gt; &gt; there is no case statement in  Squeak/Smalltalk and I can&#39;t off hand think<br>&gt; &gt; of<br>&gt; &gt; where one is needed (some Squeak users might feel they need one but that<br>&gt; &gt; is a<br>&gt; &gt; different matter).<br>&gt; &gt;<br>&gt; <br>&gt; But there is.  And it is very convenient when one doesn&#39;t want to spread a<br>&gt; case over different classes, or when the cases distribute over values of<br>&gt; the same class (e.g. integer values).  People often claim that a case<br>&gt; statement isn&#39;t necessary because one has polymorphism, but unless the<br>&gt; language supports singletons (which of course Smalltalk does not) a case<br>&gt; statement is much more readable than e.g. an if-then-else tree or a<br>&gt; &quot;Dictionary mapping values to blocks or selectors&quot; solution.<br>&gt; <br>&gt; Since you&#39;re unaware of the case statement I suggest you browse senders of<br>&gt; caseOf: and caseOf:otherwise: in Squeak trunk (which includes selectors of<br>&gt; optimized selectors that end up not being sent) or caseError, which is sent<br>&gt; when there&#39;s no otherwise clause.  Here&#39;s an example:<br>&gt; <br>&gt; menuHook: aMenu named: aSymbol shifted: aBool<br>&gt; &quot;Enhance aMenu with registered services.&quot;<br>&gt; aSymbol<br>&gt; caseOf:<br>&gt; { [ #classListMenu ] -&gt; [ ServiceGui browser: self classMenu: aMenu ].<br>&gt; [ #codePaneMenu ] -&gt; [ ServiceGui browser: self codePaneMenu: aMenu ].<br>&gt; [ #messageCategoryMenu] -&gt; [ ServiceGui browser: self messageCategoryMenu:<br>&gt; aMenu ].<br>&gt; [ #messageListMenu ] -&gt; [ ServiceGui browser: self messageListMenu: aMenu ].<br>&gt; [ #systemCategoryMenu ] -&gt; [ ServiceGui browser: self classCategoryMenu:<br>&gt; aMenu ] }<br>&gt; otherwise: [ &quot;do nothing&quot; ]<br>&gt; <br>&gt; This compiles down to a sequence of comparisons.<br><br>I was aware of caseOf: in Squeak.  I always found it awkward to use and<br>felt a true case statement would be simpler.  Alas, it&#39;s impossible to<br>have a true case statement added to Smalltalk now I think.<br><br>caseOf: is user code and thus, in principle, outside the scope of the VM.<br>For example, if I didn&#39;t want the sequential search of caseOf:  I could<br>implement a method  doBlockAt:  method in class Dictionary that assumes<br>the values stored in the dictionary are blocks and invokes the block<br>found by performing at: on the arg of doBlockAt:.<br>But the code for both caseOf: and doBlockAt: are written by users so the<br>VM can&#39;t optimize it, is forced to have the overhead of using blocks,<br>and must be locked in to the search algorithm the user has chosen (for<br>better or for worse).<br><br>&gt; &gt; The use of compare and branches might be OK in some cases<br>&gt; &gt; but a mess for the finite state machines generated from regular<br>&gt; &gt; expressions.<br>&gt; &gt; Actually, even with computed gotos  FSMs are somewhat messy but without<br>&gt; &gt; them<br>&gt; &gt; it&#39;s worse.  I don&#39;t know what  &#39;PIC dispatch&#39; is.<br>&gt; &gt;<br>&gt; <br>&gt; Polymorphic inline cache dispatch.  In JIT VMs such as Cog polymorphic send<br>&gt; sites are optimized using jump tables, one jump for each class encountered<br>&gt; at the send site, up tio some small limit such as 6 cases.  Right now in<br>&gt; Cog these jump tables are  sequential comparisons.  But in some VMs, where<br>&gt; the degree of polymorphism may be much higher (think prototype languages<br>&gt; such as JavaScript) a binary tree may be much miore efficient, if harder to<br>&gt; organize.<br>&gt; <br>&gt; To use a binary tree don&#39;t I need some kind of computed goto for when I<br>&gt; &gt; reach<br>&gt; &gt; a leaf of the tree????<br>&gt; &gt;<br>&gt; <br>&gt; No.  Once you&#39;re at the leaf you just include the bytecodes.  So for<br>&gt; example take the following case statement:<br>&gt; <br>&gt; quickPrimitiveGeneratorFor: aQuickPrimitiveIndex<br>&gt; &lt;api&gt;<br>&gt; &lt;returnTypeC: &#39;int (*quickPrimitiveGeneratorFor(sqInt<br>&gt; aQuickPrimitiveIndex))(void)&#39;&gt;<br>&gt; ^aQuickPrimitiveIndex<br>&gt; caseOf: {<br>&gt; [256] -&gt; [#genQuickReturnSelf].<br>&gt; [257] -&gt; [#genQuickReturnConstNil].<br>&gt; [258] -&gt; [#genQuickReturnConstTrue].<br>&gt; [259] -&gt; [#genQuickReturnConstFalse].<br>&gt; [260] -&gt; [#genQuickReturnConstMinusOne].<br>&gt; [261] -&gt; [#genQuickReturnConstZero].<br>&gt; [262] -&gt; [#genQuickReturnConstOne].<br>&gt; [263] -&gt; [#genQuickReturnConstTwo] }<br>&gt; otherwise: [#genQuickReturnInstVar]<br>&gt; <br>&gt; This is compiled in the current Squeak compiler as<br>&gt; <br>&gt; 61 &lt;10&gt; pushTemp: 0<br>&gt; 62 &lt;88&gt; dup<br>&gt; 63 &lt;2A&gt; pushConstant: 256<br>&gt; 64 &lt;B6&gt; send: =<br>&gt; 65 &lt;9B&gt; jumpFalse: 70<br>&gt; 66 &lt;87&gt; pop<br>&gt; 67 &lt;29&gt; pushConstant: #genQuickReturnSelf<br>&gt; 68 &lt;A4 35&gt; jumpTo: 123<br>&gt; 70 &lt;88&gt; dup<br>&gt; 71 &lt;28&gt; pushConstant: 257<br>&gt; 72 &lt;B6&gt; send: =<br>&gt; 73 &lt;9B&gt; jumpFalse: 78<br>&gt; 74 &lt;87&gt; pop<br>&gt; 75 &lt;21&gt; pushConstant: #genQuickReturnConstNil<br>&gt; 76 &lt;A4 2D&gt; jumpTo: 123<br>&gt; ...<br>&gt; 117 &lt;22&gt; pushConstant: 263<br>&gt; 118 &lt;B6&gt; send: =<br>&gt; 119 &lt;99&gt; jumpFalse: 122<br>&gt; 120 &lt;21&gt; pushConstant: #genQuickReturnConstTwo<br>&gt; 121 &lt;90&gt; jumpTo: 123<br>&gt; 122 &lt;20&gt; pushConstant: #genQuickReturnInstVar<br>&gt; 123 &lt;7C&gt; returnTop<br>&gt; <br>&gt; but it could be more efficient if the code were<br>&gt; <br>&gt;     pushTemp: 0<br>&gt;     dup<br>&gt;     pushConstant: 256<br>&gt;     send: &lt;<br>&gt;     jumpFalse: L1<br>&gt;     dup<br>&gt;     pushConstant: 260<br>&gt;     send: &lt;<br>&gt;     jumpFalse: L2<br>&gt;     dup<br>&gt;     pushConstant: 258<br>&gt;     send: &lt;<br>&gt;     jumpFalse: L3<br>&gt;     dup<br>&gt;     pushConstant: 257<br>&gt;     send: &lt;<br>&gt;     jumpFalse: L4<br>&gt;     pushConstant: #genQuickReturnSelf<br>&gt;     jumpTo: L0<br>&gt;     pushConstant: #genQuickReturnConstNil<br>&gt;     jumpTo: L0<br>&gt;     ...<br>&gt;    L1:<br>&gt;     pushConstant: #genQuickReturnInstVar<br>&gt;    L0:<br>&gt;     returnTop<br><br>I have no problem with this code per say; if Squeak, the language,<br>had a case statement it could be implemented this way.<br>But I wouldn&#39;t want to be forced to implement my FSMs this way.<br>It might be acceptable for small FSMs.<br>I want to avoid sequential search and<br> even binary search might be rather expensive.<br>I look at computed gotos as the solution but,<br>as you pointed out, computed gotos pose problems for JIT.<br>Admittedly, for large FSM&#39;s, it might be best or necessary to<br>use a FSM simulator anyway, as I do now.<br><br>&gt; &gt; - use thisContext pc: value.<br>&gt; &gt;<br>&gt; &gt; This would be a possibility for me to experiment with for now.  When I<br>&gt; &gt; have a working<br>&gt; &gt; parser generator tool I could campaign for my computed goto instructions<br>&gt; &gt; to be added<br>&gt; &gt; to the VM.<br>&gt; &gt;<br>&gt; &gt; &gt; This /should/ be fine in the stack VM, but<br>&gt; &gt; &gt; slooooow in the JIT because internally mapping bytecode pcs to machine<br>&gt; &gt; code<br>&gt; &gt; &gt; pcs is slow, and currently slower still because the frame will be<br>&gt; &gt; converted<br>&gt; &gt; &gt; to a pure context and then converted back into a frame on the return from<br>&gt; &gt; &gt; pc:.  But this solution isn&#39;t to be rejected out-of-hand.  It can be<br>&gt; &gt; &gt; optimized to avoid the frame conversion and the JIT might be able to<br>&gt; &gt; &gt; optimize it.<br>&gt; &gt;<br>&gt; &gt; I assume that if computed gotos were used the translation to machine code<br>&gt; &gt; would require a direct<br>&gt; &gt; mapping of (virtually labeled) bytecode locations to machine code<br>&gt; &gt; locations.  I think this can be done<br>&gt; &gt; in a reasonable amount of time but others such as yourself clearly<br>&gt; &gt; understand the issues far better than<br>&gt; &gt; I do.  The dirty solution to start would be to simply not JIT the code<br>&gt; &gt; that uses computed gotos.<br>&gt; &gt;<br>&gt; <br>&gt; Yes, it could be.  The JIT would generate a jump table from the literal<br>&gt; containing the bytecoded pcs, and there would be no conversion; only<br>&gt; indexing the jump table and jumping.  Again, organizing that table as a<br>&gt; binary switch may well be faster on modern architectures.  Indirect jumps<br>&gt; typically involve pipeline stalls, whereas binary jump trees don&#39;t.<br>&gt; <br>&gt; &gt; The main problem is the compiler has no support for labels so<br>&gt; &gt; &gt; there would be work here.<br>&gt; &gt;<br>&gt; &gt; I don&#39;t mind doing the work but to my way of thinking  &quot;goto X&quot; is pretty<br>&gt; &gt; basic<br>&gt; &gt; and is thus best handled at the VM/byte code level.  Anything else is doing<br>&gt; &gt; in a complicated way something that is fairly simple.  Of course changing<br>&gt; &gt; the VM/byte codes by even a single byte code is a major deal unless done<br>&gt; &gt; when the VM/byte codes are initially created.  Alas I must deal with what<br>&gt; &gt; already exists.  Even so, my preference is to work with the VM if at all<br>&gt; &gt; possible.<br>&gt; &gt;<br>&gt; &gt;<br>&gt; &gt; &gt;&gt; For example, one such language is that of regular expressions, which I<br>&gt; &gt; &gt;&gt; wish to translate into finite state machines implemented in VM code.<br>&gt; &gt; &gt;&gt; In this case I need case 2) gotos where coll is a collection of<br>&gt; &gt; &gt;&gt; associations, possibly a<br>&gt; &gt; &gt;&gt; Dictionary. I also plan to write a debugger for this (and other<br>&gt; &gt; languages)<br>&gt; &gt; &gt;&gt; but that is another story.<br>&gt; &gt; &gt;&gt;<br>&gt; &gt; &gt;&gt; I realize that the Cog VM is being built for Smalltalk (Squeak? Pharo?)<br>&gt; &gt; &gt;&gt; for which the goto instructions are not needed and thus I assume<br>&gt; &gt; &gt;&gt; unavailable. But there is something to<br>&gt; &gt; &gt;&gt; viewing a virtual machine as general purpose and thus the target of<br>&gt; &gt; &gt;&gt; multiple languages as is<br>&gt; &gt; &gt;&gt; the case for the Java virtual machine.<br>&gt; &gt; &gt;&gt; If the Cog VM is viewed this way then I argue there is a need for my<br>&gt; &gt; goto<br>&gt; &gt; &gt;&gt; instructions<br>&gt; &gt; &gt;&gt; because some languages have need for them.<br>&gt; &gt; &gt;&gt; For example, many languages have case statements.  (I am all for object<br>&gt; &gt; &gt;&gt; oriented<br>&gt; &gt; &gt;&gt; but I would be willing to accept a case statement in Smalltalk too;  the<br>&gt; &gt; &gt;&gt; Squeak code<br>&gt; &gt; &gt;&gt; implemented one in Squeak doesn&#39;t cut it).<br>&gt; &gt; &gt;<br>&gt; &gt;<br>&gt; &gt; &gt; I&#39;ve occasionally thought about this for many years.  A computed jump<br>&gt; &gt; might<br>&gt; &gt; &gt; be nice.  Eg index an Array literal of pcs with the integer on top of<br>&gt; &gt; &gt; stack, falling through on bad type or out of range.<br>&gt; &gt;<br>&gt; &gt; This is the way I am thinking.  If there are other reasons for a computed<br>&gt; &gt; jumpTo<br>&gt; &gt; as well all the better.<br>&gt; &gt;<br>&gt; &gt; &gt;&gt; Anyway, I am not arguing to Change Squeak or Smalltalk but I am arguing<br>&gt; &gt; &gt;&gt; to have my goto instructions in Cog VM. Is there any chance of this?????<br>&gt; &gt; &gt;&gt;<br>&gt; &gt;<br>&gt; &gt; &gt; There&#39;s no chance of me spending time implementing this any time soon.  I<br>&gt; &gt; &gt; have too much high-priority tasks to tackle this.  But I want to<br>&gt; &gt; encourage<br>&gt; &gt; &gt; you or others to have a go implementing it.  It&#39;s fun!<br>&gt; &gt;<br>&gt; &gt; I understand and am willing to be the one to add one or more computed jump<br>&gt; &gt; instructions, including working on the JIT code generator if needed.<br>&gt; &gt; As you say it should be fun (and also educational).  But<br>&gt; &gt;    1)  I am pretty busy now too and probably won&#39;t get to this for a year.<br>&gt; &gt;    2)  If I am to do this it would be great if someone can write a<br>&gt; &gt; specification as to<br>&gt; &gt;         what is to be done.  If someone can write this now that would be<br>&gt; &gt; great but<br>&gt; &gt;         if they write it when I post that I am ready to do the work that<br>&gt; &gt; would also<br>&gt; &gt;         be fine.<br>&gt; &gt;    3)  I don&#39;t want to just have my own private VM/byte codes.  I want<br>&gt; &gt; users of my<br>&gt; &gt;         parser generator tool to be able to load it into a standard<br>&gt; &gt; version of Squeak<br>&gt; &gt;         and run it there including the possible generation of compilers<br>&gt; &gt; for compiling<br>&gt; &gt;         their domain specific language programs into byte codes if desired.<br>&gt; &gt;<br>&gt; <br>&gt; Sure.  Get back to me when you&#39;re ready to work on it and I&#39;ll write the<br>&gt; specification, and help you with whatever info you need.  There should be<br>&gt; room in the bytecode sets we&#39;ll likely be using next year.<br><br><br>WILL DO.  SHOULD BE FUN.<br>WILL DO.  SHOULD BE FUN.<br>WILL DO.  SHOULD BE FUN.<br><br><br>&gt; <br>&gt; &gt;<br>&gt; &gt; &gt;&gt; I don&#39;t know the Squeak VM or the Cog VM either but I assume these<br>&gt; &gt; &gt;&gt; instructions don&#39;t exist because I see no need of them when the source<br>&gt; &gt; &gt;&gt; language is<br>&gt; &gt; &gt;&gt; Squeak or any version of Smalltalk for that matter. I also assume that<br>&gt; &gt; &gt;&gt; there is already<br>&gt; &gt; &gt;&gt; a full list of 256 instructions in the Cog VM and thus no room for my<br>&gt; &gt; goto<br>&gt; &gt; &gt;&gt; instructions<br>&gt; &gt; &gt;&gt; unless some instructions are removed.<br>&gt; &gt; &gt;&gt;<br>&gt; &gt; &gt;&gt; Are there Cog VM instructions that are so rarely used that they could be<br>&gt; &gt; &gt;&gt; removed without<br>&gt; &gt; &gt;&gt; unreasonably slowing down the Cog VM interpretation of byte codes<br>&gt; &gt; &gt;&gt; generated from Squeak source code?????<br>&gt; &gt; &gt;&gt;<br>&gt; &gt;<br>&gt; &gt; &gt; The current set has 3 unused bytecodes, one of which Spur uses, so<br>&gt; &gt; &gt; effectively there are two unused bytecodes.<br>&gt; &gt;<br>&gt; &gt; Levente Uzonyi  in his posting pointed out that only one instruction is<br>&gt; &gt; needed.<br>&gt; &gt; I don&#39;t like having to push the address to jump to onto the stack,<br>&gt; &gt; preferring a byte<br>&gt; &gt; code with an argument, but I could live with his solution if that is what<br>&gt; &gt; is decided.<br>&gt; &gt; In the case of  goto  coll at: X  the address is likely to end up on top<br>&gt; &gt; of the stack<br>&gt; &gt; anyway so Levente&#39;s  jumpToTop instruction looks good in any case.<br>&gt; &gt;<br>&gt; <br>&gt; If the bytecode is one that takes an integer on top of stack, and an Array<br>&gt; literal containing bytecode pcs, falling through on out of range, then<br>&gt; nothing other than the index need be pushed on top of stack.  That would be<br>&gt; my preference.<br>&gt; <br><br>Again, for my FSM, case this would often be considered to be good.<br>But if the state transition tables are sparse then Dictionaries<br>might be preferable to Arrays.<br>My expection is that  at:  be sent to the collection object<br> to get the address to go to.  Knowing that the collection<br>is an array though makes it easier for the compiler/VM to<br>ensure that the addresses stored in the collection are valid.<br>Actually, the compiler will be generating the addresses.<br>Does the VM have absolute trust in the compiler to generate valid addresses?<br>What if the compiler is generated by my parser generator tool?<br><br><br>&gt; &gt; The Cog VMs support multiple bytecode sets.  If you look at the<br>&gt; &gt; &gt; BytecodeSets package on VMMaker you can read the class comments of the<br>&gt; &gt; &gt; BytecodeEncoder subclasses such as EncoderForSistaV1.  These bytecode<br>&gt; &gt; sets<br>&gt; &gt; &gt; have a few more unused bytecodes.  This multiple bytecode set support is<br>&gt; &gt; &gt; better implemented in Spur where there is only one compiled method header<br>&gt; &gt; &gt; format and support for 64k literals.  So let me encourage you to move to<br>&gt; &gt; &gt; Spur and to look at the Sista set.  The class comment of each encoder<br>&gt; &gt; class<br>&gt; &gt; &gt; specifies the instruction set it targets.<br>&gt; &gt;<br>&gt; &gt; I am prepared to work with Spur and the Sista set.  I am looking for<br>&gt; &gt; someone to<br>&gt; &gt; say that if I do this work that incorporating the work into Spur will be<br>&gt; &gt; seriously<br>&gt; &gt; considered.<br>&gt; &gt;<br>&gt; <br>&gt; I can say that, yes.  I will seriously consider adding it.  I think its a<br>&gt; useful thing in the bytecode set, precisely to allow compiling other<br>&gt; languages to the VM.<br><br><br>GLAD TO HEAR THIS.<br><br><br>&gt; <br>&gt; <br>&gt; <br>&gt; &gt;<br>&gt; &gt; Ralph Boland<br>&gt; &gt;<br>&gt; &gt;<br>&gt; &gt;<br>&gt; <br>&gt; <br>&gt; --<br>&gt; best,<br>&gt; Eliot<br><br><br>Ralph<br></div><div class="gmail_extra"><br><div class="gmail_quote">On 3 November 2014 12:34,  <span dir="ltr">&lt;<a href="mailto:vm-dev-request@lists.squeakfoundation.org" target="_blank">vm-dev-request@lists.squeakfoundation.org</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Send Vm-dev mailing list submissions to<br>
        <a href="mailto:vm-dev@lists.squeakfoundation.org">vm-dev@lists.squeakfoundation.org</a><br>
<br>
To subscribe or unsubscribe via the World Wide Web, visit<br>
        <a href="http://lists.squeakfoundation.org/mailman/listinfo/vm-dev" target="_blank">http://lists.squeakfoundation.org/mailman/listinfo/vm-dev</a><br>
or, via email, send a message with subject or body &#39;help&#39; to<br>
        <a href="mailto:vm-dev-request@lists.squeakfoundation.org">vm-dev-request@lists.squeakfoundation.org</a><br>
<br>
You can reach the person managing the list at<br>
        <a href="mailto:vm-dev-owner@lists.squeakfoundation.org">vm-dev-owner@lists.squeakfoundation.org</a><br>
<br>
When replying, please edit your Subject line so it is more specific<br>
than &quot;Re: Contents of Vm-dev digest...&quot;<br>
<br>
<br>
Today&#39;s Topics:<br>
<br>
   1. Re: goto instruction with Cog VM (Eliot Miranda)<br>
<br>
<br>
----------------------------------------------------------------------<br>
<br>
Message: 1<br>
Date: Mon, 3 Nov 2014 11:34:48 -0800<br>
From: Eliot Miranda &lt;<a href="mailto:eliot.miranda@gmail.com">eliot.miranda@gmail.com</a>&gt;<br>
Subject: Re: [Vm-dev] goto instruction with Cog VM<br>
To: Squeak Virtual Machine Development Discussion<br>
        &lt;<a href="mailto:vm-dev@lists.squeakfoundation.org">vm-dev@lists.squeakfoundation.org</a>&gt;<br>
Message-ID:<br>
        &lt;<a href="mailto:CAC20JE1RduKQW_EdMsfah156QnTbR8USt9dEb4mj1rb15rndqA@mail.gmail.com">CAC20JE1RduKQW_EdMsfah156QnTbR8USt9dEb4mj1rb15rndqA@mail.gmail.com</a>&gt;<br>
Content-Type: text/plain; charset=&quot;utf-8&quot;<br>
<br>
Hi Ralph,<br>
<br>
On Sun, Nov 2, 2014 at 9:48 PM, Ralph Boland &lt;<a href="mailto:rpboland@gmail.com">rpboland@gmail.com</a>&gt; wrote:<br>
<br>
&gt;<br>
&gt; &gt;&gt;<br>
&gt; &gt;&gt; I am working on a parser generator tool (a replacement for SmaCC) and<br>
&gt; &gt;&gt; one of the things I a m interested in is the direct translation of<br>
&gt; &gt;&gt; language specifications into the virtual machine code (SmaCC and my<br>
&gt; &gt;&gt; current version of it use Squeak as the target language).<br>
&gt; &gt;&gt;<br>
&gt;<br>
&gt; &gt; First, a different approach than compiling to Smalltalk is to compile to<br>
&gt; a<br>
&gt; &gt; parse tree.  We do this in the pseudo JavaScript compiler we&#39;ve<br>
&gt; implemented<br>
&gt; &gt; at Cadence, translating an AST into a Squeak compiler parse tree for code<br>
&gt; &gt; generation.  Targeting a parse tree gives you much more freedom; you can<br>
&gt; &gt; express things that aren&#39;t expressible in Smalltalk.  And if you target<br>
&gt; &gt; bytecodes you can do even more.<br>
&gt;<br>
&gt;<br>
&gt; I never considered using a parse tree as the target.  An interesting idea<br>
&gt; which in many instances may be the best approach.  But for my regular<br>
&gt; expression<br>
&gt; example I would still want to generate byte codes.  In any case I wouldn&#39;t<br>
&gt; want to<br>
&gt; restrict users of my parser generator tool to any one of the three options<br>
&gt; (Smalltalk code,<br>
&gt; parse tree, byte code).  It is my responsibility to make all three options<br>
&gt; as easy and<br>
&gt; efficient as reasonably possible for users of the parser generator tool.<br>
&gt; Haven&#39;t put<br>
&gt; much thought into this yet though.   So far Smalltalk (Squeak) is the only<br>
&gt; option.<br>
&gt;<br>
&gt;<br>
&gt; &gt;&gt; One of the problems I have is that, for some languages, the natural<br>
&gt; &gt;&gt; translation<br>
&gt; &gt;&gt; into VM code uses computed gotos.<br>
&gt; &gt;&gt; There are two scenarios here:<br>
&gt; &gt;&gt;<br>
&gt; &gt;&gt;      1) goto X  where X is a variable.<br>
&gt; &gt;&gt;      2) goto  (coll at: y)  where coll is a Collection.<br>
&gt; &gt;&gt;<br>
&gt;<br>
&gt; &gt; There are several ways of implementing this without computed bytecodes in<br>
&gt; &gt; the instruction set, but there is also the possibility of implementing it<br>
&gt; &gt; directly in the instruction set.<br>
&gt;<br>
&gt; &gt; Off the top of my head one could<br>
&gt;<br>
&gt; &gt; - map to perform: using some mangled selector.  Yes this is problematic<br>
&gt; &gt; because one has to split the scope between the two methods, so in general<br>
&gt; &gt; it&#39;s not a solution<br>
&gt;<br>
&gt; Doesn&#39;t appeal to me.<br>
&gt;<br>
&gt; &gt; - map to a case statement, which is what Squeak does. Just map it to a<br>
&gt; &gt; sequence of compare and branches.  Or better still, to a binary tree.<br>
&gt; &gt; Coincidentally this is used by the JIT to implement block dispatch in<br>
&gt; &gt; methods that contain more than one block.  I know of other VM<br>
&gt; &gt; implementations using it for PIC dispatch with really good performance.<br>
&gt;<br>
&gt; I don&#39;t know what you mean my Squeak mapping to a case statement since<br>
&gt; there is no case statement in  Squeak/Smalltalk and I can&#39;t off hand think<br>
&gt; of<br>
&gt; where one is needed (some Squeak users might feel they need one but that<br>
&gt; is a<br>
&gt; different matter).<br>
&gt;<br>
<br>
But there is.  And it is very convenient when one doesn&#39;t want to spread a<br>
case over different classes, or when the cases distribute over values of<br>
the same class (e.g. integer values).  People often claim that a case<br>
statement isn&#39;t necessary because one has polymorphism, but unless the<br>
language supports singletons (which of course Smalltalk does not) a case<br>
statement is much more readable than e.g. an if-then-else tree or a<br>
&quot;Dictionary mapping values to blocks or selectors&quot; solution.<br>
<br>
Since you&#39;re unaware of the case statement I suggest you browse senders of<br>
caseOf: and caseOf:otherwise: in Squeak trunk (which includes selectors of<br>
optimized selectors that end up not being sent) or caseError, which is sent<br>
when there&#39;s no otherwise clause.  Here&#39;s an example:<br>
<br>
menuHook: aMenu named: aSymbol shifted: aBool<br>
&quot;Enhance aMenu with registered services.&quot;<br>
aSymbol<br>
caseOf:<br>
{ [ #classListMenu ] -&gt; [ ServiceGui browser: self classMenu: aMenu ].<br>
[ #codePaneMenu ] -&gt; [ ServiceGui browser: self codePaneMenu: aMenu ].<br>
[ #messageCategoryMenu] -&gt; [ ServiceGui browser: self messageCategoryMenu:<br>
aMenu ].<br>
[ #messageListMenu ] -&gt; [ ServiceGui browser: self messageListMenu: aMenu ].<br>
[ #systemCategoryMenu ] -&gt; [ ServiceGui browser: self classCategoryMenu:<br>
aMenu ] }<br>
otherwise: [ &quot;do nothing&quot; ]<br>
<br>
This compiles down to a sequence of comparisons.<br>
<br>
The use of compare and branches might be OK in some cases<br>
&gt; but a mess for the finite state machines generated from regular<br>
&gt; expressions.<br>
&gt; Actually, even with computed gotos  FSMs are somewhat messy but without<br>
&gt; them<br>
&gt; it&#39;s worse.  I don&#39;t know what  &#39;PIC dispatch&#39; is.<br>
&gt;<br>
<br>
Polymorphic inline cache dispatch.  In JIT VMs such as Cog polymorphic send<br>
sites are optimized using jump tables, one jump for each class encountered<br>
at the send site, up tio some small limit such as 6 cases.  Right now in<br>
Cog these jump tables are  sequential comparisons.  But in some VMs, where<br>
the degree of polymorphism may be much higher (think prototype languages<br>
such as JavaScript) a binary tree may be much miore efficient, if harder to<br>
organize.<br>
<br>
To use a binary tree don&#39;t I need some kind of computed goto for when I<br>
&gt; reach<br>
&gt; a leaf of the tree????<br>
&gt;<br>
<br>
No.  Once you&#39;re at the leaf you just include the bytecodes.  So for<br>
example take the following case statement:<br>
<br>
quickPrimitiveGeneratorFor: aQuickPrimitiveIndex<br>
&lt;api&gt;<br>
&lt;returnTypeC: &#39;int (*quickPrimitiveGeneratorFor(sqInt<br>
aQuickPrimitiveIndex))(void)&#39;&gt;<br>
^aQuickPrimitiveIndex<br>
caseOf: {<br>
[256] -&gt; [#genQuickReturnSelf].<br>
[257] -&gt; [#genQuickReturnConstNil].<br>
[258] -&gt; [#genQuickReturnConstTrue].<br>
[259] -&gt; [#genQuickReturnConstFalse].<br>
[260] -&gt; [#genQuickReturnConstMinusOne].<br>
[261] -&gt; [#genQuickReturnConstZero].<br>
[262] -&gt; [#genQuickReturnConstOne].<br>
[263] -&gt; [#genQuickReturnConstTwo] }<br>
otherwise: [#genQuickReturnInstVar]<br>
<br>
This is compiled in the current Squeak compiler as<br>
<br>
61 &lt;10&gt; pushTemp: 0<br>
62 &lt;88&gt; dup<br>
63 &lt;2A&gt; pushConstant: 256<br>
64 &lt;B6&gt; send: =<br>
65 &lt;9B&gt; jumpFalse: 70<br>
66 &lt;87&gt; pop<br>
67 &lt;29&gt; pushConstant: #genQuickReturnSelf<br>
68 &lt;A4 35&gt; jumpTo: 123<br>
70 &lt;88&gt; dup<br>
71 &lt;28&gt; pushConstant: 257<br>
72 &lt;B6&gt; send: =<br>
73 &lt;9B&gt; jumpFalse: 78<br>
74 &lt;87&gt; pop<br>
75 &lt;21&gt; pushConstant: #genQuickReturnConstNil<br>
76 &lt;A4 2D&gt; jumpTo: 123<br>
...<br>
117 &lt;22&gt; pushConstant: 263<br>
118 &lt;B6&gt; send: =<br>
119 &lt;99&gt; jumpFalse: 122<br>
120 &lt;21&gt; pushConstant: #genQuickReturnConstTwo<br>
121 &lt;90&gt; jumpTo: 123<br>
122 &lt;20&gt; pushConstant: #genQuickReturnInstVar<br>
123 &lt;7C&gt; returnTop<br>
<br>
but it could be more efficient if the code were<br>
<br>
    pushTemp: 0<br>
    dup<br>
    pushConstant: 256<br>
    send: &lt;<br>
    jumpFalse: L1<br>
    dup<br>
    pushConstant: 260<br>
    send: &lt;<br>
    jumpFalse: L2<br>
    dup<br>
    pushConstant: 258<br>
    send: &lt;<br>
    jumpFalse: L3<br>
    dup<br>
    pushConstant: 257<br>
    send: &lt;<br>
    jumpFalse: L4<br>
    pushConstant: #genQuickReturnSelf<br>
    jumpTo: L0<br>
    pushConstant: #genQuickReturnConstNil<br>
    jumpTo: L0<br>
    ...<br>
   L1:<br>
    pushConstant: #genQuickReturnInstVar<br>
   L0:<br>
    returnTop<br>
<br>
&gt; - use thisContext pc: value.<br>
&gt;<br>
&gt; This would be a possibility for me to experiment with for now.  When I<br>
&gt; have a working<br>
&gt; parser generator tool I could campaign for my computed goto instructions<br>
&gt; to be added<br>
&gt; to the VM.<br>
&gt;<br>
&gt; &gt; This /should/ be fine in the stack VM, but<br>
&gt; &gt; slooooow in the JIT because internally mapping bytecode pcs to machine<br>
&gt; code<br>
&gt; &gt; pcs is slow, and currently slower still because the frame will be<br>
&gt; converted<br>
&gt; &gt; to a pure context and then converted back into a frame on the return from<br>
&gt; &gt; pc:.  But this solution isn&#39;t to be rejected out-of-hand.  It can be<br>
&gt; &gt; optimized to avoid the frame conversion and the JIT might be able to<br>
&gt; &gt; optimize it.<br>
&gt;<br>
&gt; I assume that if computed gotos were used the translation to machine code<br>
&gt; would require a direct<br>
&gt; mapping of (virtually labeled) bytecode locations to machine code<br>
&gt; locations.  I think this can be done<br>
&gt; in a reasonable amount of time but others such as yourself clearly<br>
&gt; understand the issues far better than<br>
&gt; I do.  The dirty solution to start would be to simply not JIT the code<br>
&gt; that uses computed gotos.<br>
&gt;<br>
<br>
Yes, it could be.  The JIT would generate a jump table from the literal<br>
containing the bytecoded pcs, and there would be no conversion; only<br>
indexing the jump table and jumping.  Again, organizing that table as a<br>
binary switch may well be faster on modern architectures.  Indirect jumps<br>
typically involve pipeline stalls, whereas binary jump trees don&#39;t.<br>
<br>
&gt; The main problem is the compiler has no support for labels so<br>
&gt; &gt; there would be work here.<br>
&gt;<br>
&gt; I don&#39;t mind doing the work but to my way of thinking  &quot;goto X&quot; is pretty<br>
&gt; basic<br>
&gt; and is thus best handled at the VM/byte code level.  Anything else is doing<br>
&gt; in a complicated way something that is fairly simple.  Of course changing<br>
&gt; the VM/byte codes by even a single byte code is a major deal unless done<br>
&gt; when the VM/byte codes are initially created.  Alas I must deal with what<br>
&gt; already exists.  Even so, my preference is to work with the VM if at all<br>
&gt; possible.<br>
&gt;<br>
&gt;<br>
&gt; &gt;&gt; For example, one such language is that of regular expressions, which I<br>
&gt; &gt;&gt; wish to translate into finite state machines implemented in VM code.<br>
&gt; &gt;&gt; In this case I need case 2) gotos where coll is a collection of<br>
&gt; &gt;&gt; associations, possibly a<br>
&gt; &gt;&gt; Dictionary. I also plan to write a debugger for this (and other<br>
&gt; languages)<br>
&gt; &gt;&gt; but that is another story.<br>
&gt; &gt;&gt;<br>
&gt; &gt;&gt; I realize that the Cog VM is being built for Smalltalk (Squeak? Pharo?)<br>
&gt; &gt;&gt; for which the goto instructions are not needed and thus I assume<br>
&gt; &gt;&gt; unavailable. But there is something to<br>
&gt; &gt;&gt; viewing a virtual machine as general purpose and thus the target of<br>
&gt; &gt;&gt; multiple languages as is<br>
&gt; &gt;&gt; the case for the Java virtual machine.<br>
&gt; &gt;&gt; If the Cog VM is viewed this way then I argue there is a need for my<br>
&gt; goto<br>
&gt; &gt;&gt; instructions<br>
&gt; &gt;&gt; because some languages have need for them.<br>
&gt; &gt;&gt; For example, many languages have case statements.  (I am all for object<br>
&gt; &gt;&gt; oriented<br>
&gt; &gt;&gt; but I would be willing to accept a case statement in Smalltalk too;  the<br>
&gt; &gt;&gt; Squeak code<br>
&gt; &gt;&gt; implemented one in Squeak doesn&#39;t cut it).<br>
&gt; &gt;<br>
&gt;<br>
&gt; &gt; I&#39;ve occasionally thought about this for many years.  A computed jump<br>
&gt; might<br>
&gt; &gt; be nice.  Eg index an Array literal of pcs with the integer on top of<br>
&gt; &gt; stack, falling through on bad type or out of range.<br>
&gt;<br>
&gt; This is the way I am thinking.  If there are other reasons for a computed<br>
&gt; jumpTo<br>
&gt; as well all the better.<br>
&gt;<br>
&gt; &gt;&gt; Anyway, I am not arguing to Change Squeak or Smalltalk but I am arguing<br>
&gt; &gt;&gt; to have my goto instructions in Cog VM. Is there any chance of this?????<br>
&gt; &gt;&gt;<br>
&gt;<br>
&gt; &gt; There&#39;s no chance of me spending time implementing this any time soon.  I<br>
&gt; &gt; have too much high-priority tasks to tackle this.  But I want to<br>
&gt; encourage<br>
&gt; &gt; you or others to have a go implementing it.  It&#39;s fun!<br>
&gt;<br>
&gt; I understand and am willing to be the one to add one or more computed jump<br>
&gt; instructions, including working on the JIT code generator if needed.<br>
&gt; As you say it should be fun (and also educational).  But<br>
&gt;    1)  I am pretty busy now too and probably won&#39;t get to this for a year.<br>
&gt;    2)  If I am to do this it would be great if someone can write a<br>
&gt; specification as to<br>
&gt;         what is to be done.  If someone can write this now that would be<br>
&gt; great but<br>
&gt;         if they write it when I post that I am ready to do the work that<br>
&gt; would also<br>
&gt;         be fine.<br>
&gt;    3)  I don&#39;t want to just have my own private VM/byte codes.  I want<br>
&gt; users of my<br>
&gt;         parser generator tool to be able to load it into a standard<br>
&gt; version of Squeak<br>
&gt;         and run it there including the possible generation of compilers<br>
&gt; for compiling<br>
&gt;         their domain specific language programs into byte codes if desired.<br>
&gt;<br>
<br>
Sure.  Get back to me when you&#39;re ready to work on it and I&#39;ll write the<br>
specification, and help you with whatever info you need.  There should be<br>
room in the bytecode sets we&#39;ll likely be using next year.<br>
<br>
<br>
&gt;<br>
&gt; &gt;&gt; I don&#39;t know the Squeak VM or the Cog VM either but I assume these<br>
&gt; &gt;&gt; instructions don&#39;t exist because I see no need of them when the source<br>
&gt; &gt;&gt; language is<br>
&gt; &gt;&gt; Squeak or any version of Smalltalk for that matter. I also assume that<br>
&gt; &gt;&gt; there is already<br>
&gt; &gt;&gt; a full list of 256 instructions in the Cog VM and thus no room for my<br>
&gt; goto<br>
&gt; &gt;&gt; instructions<br>
&gt; &gt;&gt; unless some instructions are removed.<br>
&gt; &gt;&gt;<br>
&gt; &gt;&gt; Are there Cog VM instructions that are so rarely used that they could be<br>
&gt; &gt;&gt; removed without<br>
&gt; &gt;&gt; unreasonably slowing down the Cog VM interpretation of byte codes<br>
&gt; &gt;&gt; generated from Squeak source code?????<br>
&gt; &gt;&gt;<br>
&gt;<br>
&gt; &gt; The current set has 3 unused bytecodes, one of which Spur uses, so<br>
&gt; &gt; effectively there are two unused bytecodes.<br>
&gt;<br>
&gt; Levente Uzonyi  in his posting pointed out that only one instruction is<br>
&gt; needed.<br>
&gt; I don&#39;t like having to push the address to jump to onto the stack,<br>
&gt; preferring a byte<br>
&gt; code with an argument, but I could live with his solution if that is what<br>
&gt; is decided.<br>
&gt; In the case of  goto  coll at: X  the address is likely to end up on top<br>
&gt; of the stack<br>
&gt; anyway so Levente&#39;s  jumpToTop instruction looks good in any case.<br>
&gt;<br>
<br>
If the bytecode is one that takes an integer on top of stack, and an Array<br>
literal containing bytecode pcs, falling through on out of range, then<br>
nothing other than the index need be pushed on top of stack.  That would be<br>
my preference.<br>
<br>
&gt; The Cog VMs support multiple bytecode sets.  If you look at the<br>
&gt; &gt; BytecodeSets package on VMMaker you can read the class comments of the<br>
&gt; &gt; BytecodeEncoder subclasses such as EncoderForSistaV1.  These bytecode<br>
&gt; sets<br>
&gt; &gt; have a few more unused bytecodes.  This multiple bytecode set support is<br>
&gt; &gt; better implemented in Spur where there is only one compiled method header<br>
&gt; &gt; format and support for 64k literals.  So let me encourage you to move to<br>
&gt; &gt; Spur and to look at the Sista set.  The class comment of each encoder<br>
&gt; class<br>
&gt; &gt; specifies the instruction set it targets.<br>
&gt;<br>
&gt; I am prepared to work with Spur and the Sista set.  I am looking for<br>
&gt; someone to<br>
&gt; say that if I do this work that incorporating the work into Spur will be<br>
&gt; seriously<br>
&gt; considered.<br>
&gt;<br>
<br>
I can say that, yes.  I will seriously consider adding it.  I think its a<br>
useful thing in the bytecode set, precisely to allow compiling other<br>
languages to the VM.<br>
<br>
<br>
<br>
&gt;<br>
&gt; Ralph Boland<br>
&gt;<br>
&gt;<br>
&gt;<br>
<br>
<br>
--<br>
best,<br>
Eliot<br>
-------------- next part --------------<br>
An HTML attachment was scrubbed...<br>
URL: <a href="http://lists.squeakfoundation.org/pipermail/vm-dev/attachments/20141103/469369c9/attachment.htm" target="_blank">http://lists.squeakfoundation.org/pipermail/vm-dev/attachments/20141103/469369c9/attachment.htm</a><br>
<br>
------------------------------<br>
<br>
_______________________________________________<br>
Vm-dev mailing list<br>
<a href="mailto:Vm-dev@lists.squeakfoundation.org">Vm-dev@lists.squeakfoundation.org</a><br>
<a href="http://lists.squeakfoundation.org/mailman/listinfo/vm-dev" target="_blank">http://lists.squeakfoundation.org/mailman/listinfo/vm-dev</a><br>
<br>
<br>
End of Vm-dev Digest, Vol 101, Issue 7<br>
**************************************<br>
</blockquote></div><br><br clear="all"><br>-- <br><div class="gmail_signature"><div dir="ltr"><h1>-- Those who can make you believe absurdities, can make you commit atrocities -- Voltaire</h1></div></div>
</div>