[Vm-dev] VM Maker: VMMaker.oscog-eem.253.mcz

Eliot Miranda eliot.miranda at gmail.com
Sun Jan 13 02:59:52 UTC 2013


On Sat, Jan 12, 2013 at 1:40 PM, Ryan Macnak <rmacnak at gmail.com> wrote:

>
> In Smalltalk, one knows at compile-time at which class to begin lookup for
> super sends. In Newspeak, we do not know this as all methods are defined by
> mixins, and the superclass of a mixin application is not known until
> runtime. Hence /dynamic/ super send.
>
> In Newspeak's as-yet-unimplemented access control, super sends can
> activate protected members, but normal sends cannot. An /absent receiver/
> send means that the receiver of the message is not on stack beneath the
> arguments like a normal send. This will allow the VM to implement access
> control without having to check whether the receiver is allowed for types
> of sends that access protected or private members, because the VM will
> provide the receiver during the send itself.
>

+1.  But there's another aspect to it.  Newspeak, like self, does not
require one to explicitly supply self as the receiver of self-sends.
 Further, Newspeak is a lexically-scoped language (like Beta) so that one
always writes methods within the scope of a class definition, and other
than top-level classes, writes a class in the scope of an outer class.  The
methods defined in outer classes are hence still in scope in inner methods.
 e.g. in the following (excuse syntax errors)

    class Outer () (
        anOuterMethod = (^'This is the result of an outer method')
        class Inner () (
            anInnerMethod = ( ^anOuterMethod )
            anOtherInnerMethod = ( ^anInnerMethod )
        )
    )

the method anOuterMethod is in scope throughout class Inner.  So that when
one writes ^anOuterMethod in anInnerMethod this is *not* equivalent to
^self anOuterMethod.  instead the receiver is actually the class Outer.

So in Newspeak sends without a receiver are "absent receiver" sends or
"implicit receiver" and the binding machinery must find the implicit
receiver for an implicit receiver send by searching along the lexical chain
*not* the inheritance chain.  The class Inner does not inherit from class
Outer; it inherits from whatever class we specify at module creation, e.g.
its superclass could be some class imported into the module when it is
instantiated.  We *don't* want an inherited definition of e.g.
anOuterMethod to override anOuterMethod because then the language would no
longer be lexically-scoped.

Now, in the first implementation of Newspeak above Squeak we added a
bytecode pushImplicitReceiverForSelector that would do a lexical lookup of
a selector and push the receiver along the lexical chain that implemented
selector.  pushImplicitReceiverForSelector would always be paired with a
subsequent send of selector.  But this is unsatisfactory, a) because of the
security concerns Ryan mentions above, and b) because the two bytecodes are
a waste; they always go together and c) there's a hole because if the
method is removed between pushImplicitReceiverForSelector and its send we'd
get an erroneous MNU.

In the new bytecode set we therefore implemented absent receiver sends such
that the receiver is actually determined by the send bytecode.  The
compiler arranges to push the arguments, but not the receiver, and the
receiver is pushed at send time (hence the arguments needs to be shuffled
down the stack and the receiver inserted, something that the JIT can do
efficiently in many cases since arguments are passed in registers for low
arity sends and there is often nothing on the stack to shuffle).

So briefly, in Newspeak an implicit receiver send is a send without an
explicit receiver that is found by looking up the lexical chain, not the
inheritance chain.

See http://bracha.org/newspeak-spec.pdf.

On Sat, Jan 12, 2013 at 3:35 AM, stephane ducasse <
> stephane.ducasse at gmail.com> wrote:
>
>>
>> Hi eliot
>>
>> I'm curious: what is a absent receiver dynamic super send?
>>
>> Stef
>> On Jan 10, 2013, at 11:27 PM, commits at source.squeak.org wrote:
>>
>> >
>> > Eliot Miranda uploaded a new version of VMMaker to project VM Maker:
>> > http://source.squeak.org/VMMaker/VMMaker.oscog-eem.253.mcz
>> >
>> > ==================== Summary ====================
>> >
>> > Name: VMMaker.oscog-eem.253
>> > Author: eem
>> > Time: 10 January 2013, 3:26:03.577 pm
>> > UUID: 4a3ac3fb-d367-478b-ad95-ad3bb8b6216f
>> > Ancestors: VMMaker.oscog-eem.252
>> >
>> > Implement absent receiver dynamic super send bytecode in the JIT.
>> > This was an oversight from implementing absent receiver send.
>> > Refactor the dynamic super send code to accomodate the new send.
>> >
>> > =============== Diff against VMMaker.oscog-eem.252 ===============
>> >
>> > Item was changed:
>> >  ----- Method: SimpleStackBasedCogit>>genDynamicSuperSendBytecode (in
>> category 'bytecode generators') -----
>> >  genDynamicSuperSendBytecode
>> > +     ^self genSendDynamicSuper: (coInterpreter literal: byte2
>> ofMethod: methodObj) numArgs: byte1!
>> > -     | numArgs selector |
>> > -     numArgs := byte1.
>> > -     selector := coInterpreter literal: byte2 ofMethod: methodObj.
>> > -     (objectMemory isYoung: selector) ifTrue:
>> > -             [hasYoungReferent := true].
>> > -     self assert: needsFrame.
>> > -     self MoveMw: numArgs * BytesPerWord r: SPReg R: ReceiverResultReg.
>> > -     numArgs > 2 ifTrue:
>> > -             [self MoveCq: numArgs R: SendNumArgsReg].
>> > -     self MoveCw: selector R: ClassReg.
>> > -     self CallNewspeakSend: (dynamicSuperSendTrampolines at: (numArgs
>> min: NumSendTrampolines - 1)).
>> > -     self flag: 'currently caller pushes result'.
>> > -     self PushR: ReceiverResultReg.
>> > -     ^0!
>> >
>> > Item was changed:
>> >  ----- Method:
>> SimpleStackBasedCogit>>genExtSendAbsentDynamicSuperBytecode (in category
>> 'bytecode generators') -----
>> >  genExtSendAbsentDynamicSuperBytecode
>> >       "241            11110001        i i i i i j j j Send To Absent
>> Dynamic Superclass Literal Selector #iiiii (+ Extend A * 32) with jjj (+
>> Extend B * 8) Arguments"
>> > +     | litIndex nArgs |
>> > +     litIndex := (byte1 >> 3) + (extA << 5).
>> > +     extA := 0.
>> > +     nArgs := (byte1 bitAnd: 7) + (extB << 3).
>> > +     extB := 0.
>> > +     ^self genSendAbsentDynamicSuper: (coInterpreter literal: litIndex
>> ofMethod: methodObj) numArgs: nArgs!
>> > -     self shouldBeImplemented.
>> > -     ^EncounteredUnknownBytecode!
>> >
>> > Item was added:
>> > + ----- Method:
>> SimpleStackBasedCogit>>genSendAbsentDynamicSuper:numArgs: (in category
>> 'bytecode generators') -----
>> > + genSendAbsentDynamicSuper: selector numArgs: numArgs
>> > +     "Shuffle arguments if necessary and push receiver.
>> > +      Then send."
>> > +     <inline: false>
>> > +     numArgs = 0
>> > +             ifTrue:
>> > +                     [self PushR: ReceiverResultReg]
>> > +             ifFalse:
>> > +                     [self MoveMw: 0 r: SPReg R: TempReg.
>> > +                     self PushR: TempReg.
>> > +                     2 to: numArgs do:
>> > +                             [:index|
>> > +                             self MoveMw: index * BytesPerWord r:
>> SPReg R: TempReg.
>> > +                             self MoveR: TempReg Mw: index - 1 *
>> BytesPerWord r: SPReg].
>> > +                     "if we copied the code in genSendDynamicSuper: we
>> could save an instruction.
>> > +                     But we care not; the smarts are in
>> StackToRegisterMappingCogit et al"
>> > +                     self MoveR: ReceiverResultReg Mw: numArgs *
>> BytesPerWord r: SPReg].
>> > +     ^self genSendDynamicSuper: selector numArgs: numArgs!
>> >
>> > Item was added:
>> > + ----- Method: SimpleStackBasedCogit>>genSendDynamicSuper:numArgs: (in
>> category 'bytecode generators') -----
>> > + genSendDynamicSuper: selector numArgs: numArgs
>> > +     (objectMemory isYoung: selector) ifTrue:
>> > +             [hasYoungReferent := true].
>> > +     self assert: needsFrame.
>> > +     self MoveMw: numArgs * BytesPerWord r: SPReg R: ReceiverResultReg.
>> > +     numArgs > 2 ifTrue:
>> > +             [self MoveCq: numArgs R: SendNumArgsReg].
>> > +     self MoveCw: selector R: ClassReg.
>> > +     self CallNewspeakSend: (dynamicSuperSendTrampolines at: (numArgs
>> min: NumSendTrampolines - 1)).
>> > +     self flag: 'currently caller pushes result'.
>> > +     self PushR: ReceiverResultReg.
>> > +     ^0!
>> >
>> > Item was removed:
>> > - ----- Method:
>> StackToRegisterMappingCogit>>genDynamicSuperSendBytecode (in category
>> 'bytecode generators') -----
>> > - genDynamicSuperSendBytecode
>> > -     | numArgs selector |
>> > -     numArgs := byte1.
>> > -     selector := coInterpreter literal: byte2 ofMethod: methodObj.
>> > -     self marshallSendArguments: numArgs.
>> > -     ^self genMarshalledSendDynamicSuper: selector numArgs: numArgs!
>> >
>> > Item was added:
>> > + ----- Method:
>> StackToRegisterMappingCogit>>genSendAbsentDynamicSuper:numArgs: (in
>> category 'bytecode generators') -----
>> > + genSendAbsentDynamicSuper: selector numArgs: numArgs
>> > +     "OK, we could do better and avoid spilling ReceiverResultReg if
>> we refactored
>> > +      marshallImplicitReceiverSendArguments: to take a flag saying
>> whether the
>> > +      receiver was in ReceiverResultReg (absent receiver send) or on
>> the stack
>> > +      (absent dynamic super send) and in the latter case loading
>> ReceiverResultReg
>> > +      from the stack after marshalling.  But this is a rare bytecode
>> so for the moment
>> > +      don't bother."
>> > +     self ssAllocateCallReg: ReceiverResultReg.
>> > +     self MoveMw: FoxMFReceiver r: FPReg R: ReceiverResultReg.
>> > +     self marshallImplicitReceiverSendArguments: numArgs.
>> > +     ^self genMarshalledSendDynamicSuper: selector numArgs: numArgs!
>> >
>> > Item was added:
>> > + ----- Method:
>> StackToRegisterMappingCogit>>genSendDynamicSuper:numArgs: (in category
>> 'bytecode generators') -----
>> > + genSendDynamicSuper: selector numArgs: numArgs
>> > +     self marshallSendArguments: numArgs.
>> > +     ^self genMarshalledSendDynamicSuper: selector numArgs: numArgs!
>> >
>>
>>
>
>


-- 
best,
Eliot
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.squeakfoundation.org/pipermail/vm-dev/attachments/20130112/9575c8e1/attachment-0001.htm


More information about the Vm-dev mailing list