[Vm-dev] Sista byte code documentation

Eliot Miranda eliot.miranda at gmail.com
Wed Jul 1 16:33:52 UTC 2020


Hi Vanessa,

  one very important facet of the extensions design is not sufficiently
explicit in the InstructionStream methods, or in EncoderForSistaV1's class
comment, which says only this:

"N.B.  Extension bytecodes can only come before extensible bytecodes, and
only if valid (one cannot extend a bytecode extensible by Ext A with an Ext
B).  An extensible bytecode consumes (and zeros) its extension(s).  Hence
the hidden implicit variables holding extensions are always zero except
after a valid sequence of extension bytecodes."

In a real bytecode interpreter the implications are as follows:
0. an Interpreter should use *static* variables for extA and extB and
initialize them to zero.  For example, they *do not* need to be initialized
on every method activation.
1. an interpreter can, and should, entirely ignore extA and extB in all
bytecodes other than those that take extensions.  So for example the vast
majority of one-byte bytecodes do not read extA or extB.
2. It is an error for a code generator to emit extension bytecodes before
any bytecode that does not take extensions.  Further, it is an error for a
code generator to emit extA before a bytecode that only takes extB
extensions and vice verse.
3. it is the responsibility of any bytecode that consumes extensions to
reset the extA and/or extB variables to zero after it has consumed their
values

Given these constraints extensions are very cheap:
- they are written to only on initialization, when creating extension
values via the extension bytecodes, and after being consumed by a bytecode
that takes extensions
- they are read only by bytecodes that take extensions, so high
dynamic-frequency single-byte bytecodes pay no penalty for the 3extensions
design

Note that these constraints are not possible to observe in
InstructionStream because there is no where (cheap and convenient) to store
the extA and extB values.  Hence the crude implementation in
*interpretNextSistaV1InstructionFor:*

On Tue, Jun 30, 2020 at 4:29 PM Eliot Miranda <eliot.miranda at gmail.com>
wrote:

> Hi Vanessa,
>
>    Clément pointed you to good sources.  The most concise guide to
> implementing them is however in the standard trunk image itself in the
> "decoding - private - sista v1" category of InstructionStream.
> To support multiple bytecode sets CompiledCode maintains a flag bit in its
> header word that selects one of two bytecode sets, represented as
> BytecodeEncoder subclasses in the CompiledCode class
> vars PrimaryBytecodeSetEncoderClass & SecondaryBytecodeSetEncoderClass. A
> CompiledCode answers the relevant class via CompiledCode>>encoderClass
> which tests the bit and answers the relevant class.  Then double
> dispatching is used to invoke the relevant bytecode set decode:
>
> *InstructionStream methods for instruction decode*
> *interpretNextInstructionFor:* client
> "*Send to the argument, client, a message that specifies the type of the
> next instruction.*"
>
> ^self method encoderClass interpretNextInstructionFor: client in: self
>
> *EncoderForV3PlusClosures class methods for instruction stream support*
> *interpretNextInstructionFor:* aClient *in:* anInstructionStream
> "*Double-dispatch through the encoder to select the correct instruction
> set decoder.*"
> ^anInstructionStream interpretNextV3ClosuresInstructionFor: aClient
>
> *EncoderForSistaV1 class methods for instruction stream support*
> *interpretNextInstructionFor:* aClient *in:* anInstructionStream
> "*Double-dispatch through the encoder to select the correct instruction
> set decoder.*"
> ^anInstructionStream interpretNextSistaV1InstructionFor: aClient
>
> which gets us back to the decoders in InstructionStream.  In particular,
> *InstructionStream methods for decoding - private - sista v1*
> *interpretNextSistaV1InstructionFor:* client
> "*Send to the argument, client, a message that specifies the next
> instruction.*"
>
> | byte div16 offset method extA extB savedPC |
> method := self method.
> "*For a table of the bytecode set, see EncoderForSistaV1's class comment.*
> "
> "*consume and compute any extensions first.*"
> extA := extB := 0.
> savedPC := pc.
> [byte := self method at: pc.
> pc := pc + 1.
> byte >= 16rE0 and: [byte <= 16rE1]] whileTrue:
> [| extByte |
> extByte := self method at: pc.
> pc := pc + 1.
> byte = 16rE0
> ifTrue:
> [extA := (extA bitShift: 8) + extByte]
> ifFalse:
> [extB := (extB = 0 and: [extByte > 127])
> ifTrue: [extByte - 256]
> ifFalse: [(extB bitShift: 8) + extByte]]].
> div16 := byte // 16.
> offset := byte \\ 16.
> "*We do an inline quasi-binary search on each of the possible 16 values
> of div16*"
> ... all the one byte codes elided...
> "*2 byte and 3 byte codes*"
> byte < 248 ifTrue:
> [^self interpretNext2ByteSistaV1Instruction: byte for: client extA: extA
> extB: extB startPC: savedPC].
> ^self interpretNext3ByteSistaV1Instruction: byte for: client extA: extA
> extB: extB startPC: savedPC
>
>
> and then all remaining implementation is in Context.
>
> On Mon, Jun 29, 2020 at 9:34 PM Vanessa Freudenberg <vanessa at codefrau.net>
> wrote:
>
>>
>> Eliot / Clément / Everyone -
>>
>> What’s the best documentation for the new byte codes?
>>
>> I found the 2014 paper, and Clèment’s thesis, and I don’t think either is
>> detailed enough to implement them correctly. Just wondering if there’s
>> anything else I could peruse other than the VM source code.
>>
>> Cheers!
>> Vanessa
>>
>>
>>
>
> --
> _,,,^..^,,,_
> best, Eliot
>


-- 
_,,,^..^,,,_
best, Eliot
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.squeakfoundation.org/pipermail/vm-dev/attachments/20200701/92fa3d9e/attachment.html>


More information about the Vm-dev mailing list