<div dir="ltr">Hi Ryan, Hi Tim, Hi Clément, and anyone else interested in Cogit arcana,<div><br></div><div>   Sista needs a directed super send bytecode.  A normal super bytecode takes the class above which to start the lookup implicitly from the method class (the last literal in a method).  A directed super send takes the class above which to start the lookup as an explicit parameter.  In Ssta&#39;s case we&#39;re pushing the class association on the stack immediately before the super send bytecode, and marking the super send bytecode as directed using a flag bit in one of the extensions.</div><div><br></div><div>Compiling a directed super is trivial; simply make the literal variable that was notionally pushed on the stack an argument of a new ceSendDirectedSuper trampoline.  But this implies that when a linked directed super send bytecode is unlinked (e.g. method redefinition or method zone compaction) we can map back to this ceSendDirectedSuper tramp[oline.</div><div><br></div><div>Up until now, the different send trampolines have been identified by looking at the alignment of the linked call instruction; every different kind of send needs a different entry point in the target method at a different alignment.  This worked well when there were only self and super sends.  It also meant that there was only a single method map type for sends, which kept the method metadata small.  Now Newspeak has two more send types; Sista will use three.  On x86 each alignment can be generated by adding a 1 byte nop in the right place.  Methods themselves are aligned on 8-byte boundaries, so the scheme would extend to 8 different send types at a pinch on x86.  Of course on ARM this doesn&#39;t work well at all; instructions are 4 bytes, and so 8 byte alignment gives only two different alignments, and we were planning to extend the method alignment to e.g. 16 bytes.</div><div><br></div><div>But all this puts extra code in the entry sequence albeit only in the form of nops.  But unlinking is extremely rare so we&#39;re letting the tail wag the dog.  Instead, I&#39;m going to revise the method metadata scheme so there&#39;s a modifier byte we can use to further distinguish send types.  We can still distinguish checked sends from unchecked sends based on alignment.  But we can distinguish between the different checked sends and the different unchecked send types by using one map code to code for a prefix.</div><div><br></div><div>A map byte has a 5 bit displacement (the distance in machine code units to the next map byte&#39;s target), and a 3 bit code in the most significant bits.  Here&#39;s the existing assignments:</div><div><br></div><div><div><span class="" style="white-space:pre">        </span>IsSendCall := 7.</div><div><span class="" style="white-space:pre">        </span>IsRelativeCall := 6.</div><div><span class="" style="white-space:pre">        </span>HasBytecodePC := 5.</div><div><span class="" style="white-space:pre">        </span>IsAbsPCReference := 4.</div><div><span class="" style="white-space:pre">        </span>IsObjectReference := 3.</div><div><span class="" style="white-space:pre">        </span>IsNSSendCall := NewspeakVM ifTrue: [2].</div><div><span class="" style="white-space:pre">        </span>IsDisplacementX2N := 1.</div><div><span class="" style="white-space:pre">        </span>IsDisplacement := 0.</div><div><span class="" style="white-space:pre">        </span>AnnotationShift := 5.</div><div><br></div><div>So if we nuke IsNSSendCall we can do e.g.</div><div><span style="white-space:pre">        AnnotationExtension := 2</span></div><div><span style="white-space:pre">interpret the displacement of an </span><span style="white-space:pre">AnnotationExtension as 0, and use the 5-bit field to extend the type of the subsequent map byte.  We then</span><span style="white-space:pre"> use two map bytes for exotic sends, suddenly making lots of send types possible without contortions.</span></div><div>--  </div><div class="gmail_signature">best,<div>Eliot</div></div>
</div></div>