2015-10-08 9:39 GMT+02:00 Eliot Miranda <eliot.mira...@gmail.com>:

> Hi Nicolai,
>
> On Thu, Oct 8, 2015 at 12:09 AM, Nicolai Hess <nicolaih...@web.de> wrote:
>
>>
>>
>> 2015-10-08 1:30 GMT+02:00 Eliot Miranda <eliot.mira...@gmail.com>:
>>
>>> Hi Nicolai,
>>>
>>> On Wed, Oct 7, 2015 at 2:13 PM, Nicolai Hess <nicolaih...@web.de> wrote:
>>>
>>>>
>>>>
>>>> 2015-10-07 16:49 GMT+02:00 Marcus Denker <marcus.den...@inria.fr>:
>>>>
>>>>>
>>>>> > On 07 Oct 2015, at 15:49, Marco Naddeo <nad...@di.unito.it> wrote:
>>>>> >
>>>>> > Hi,
>>>>> >
>>>>> > I have some problems with the large block at bottom:
>>>>> >
>>>>> > -sending the message argumentNames gives me an empty array #()
>>>>> > -sending the message sourceNode gives me a strange result and not a
>>>>> RBBlockNode, as I would expect
>>>>> >
>>>>>
>>>>> This happens already with:
>>>>>
>>>>> [  :h :s :v |    | min chroma hdash X red green blue | ] sourceNode
>>>>>
>>>>> I will check… it is a bug in the mapping pc -> AST.
>>>>>
>>>>
>>>> That's interesting, the way the pc is mapped to the AST (ir
>>>> instructionForPC: )
>>>> takes the "length" of the instruction bytecode into account and the
>>>> length of a pushclosure includes
>>>> all bytes needed for the pushing the local temps (pushConstant nil.
>>>> pushConstant nil ....)
>>>>
>>>> But the startPC of a block context starts at the first push, not after,
>>>> that means
>>>>
>>>> self method sourceNodeForPC: self startpc - 1
>>>> starts the search after the push closure bytecode but before any push
>>>> local temp byte code.
>>>>
>>>> Either we don't include the bytecodes for the "pushConstant:nil" in the
>>>> bytecode offset, or we start the search at
>>>>
>>>> self method sourceNodeForPC: self startpc - 1 + self numLocalTemps
>>>>
>>>
>>> No, no, no, no, no :-).
>>>
>>
>> I think I will always get confused by BlockClosure code at the bytecode
>> level :)
>>
>
> What exactly do you find confusing?
>

For a moment, I was unsure in which context the pushConstant:nil are
executed, on construction or when executing the block.


> The byte codes are simple if you read the right source.  Perhaps you could
> talk with Clément; he's local and understands the byte code set as well as
> I do.  If you can't talk to him you could read the class comment of
> EncoderForV3PlusClosures in a Squeak 4.6 or 5.0 image, or the class comment
> of EncoderForSistaV1 in the BytecodeSets package on
> http://source.squeak.org/VMMaker.
>
> If you're confused by the scheme for closing over variables have you read
> my blog posts on the closure compiler?
>

Yes I read your blog and it is a great source of information, not only
about the current state and what is new, but even about the history of the
smalltalk vm - this is always good to know.


>
> I wish you hadn't deleted this bit, it is "the truth":
>

I didn't want to hide "the truth" :) I thought this was the same I wrote
and understand, the startPC starts at the first pushConstant:nil for
creating space, for the local temp, on the stack.


>
> "*The PC in question is the pc of the block creation byte code.  The
> startpc of a block is the first bytecode following the block creation byte
> code.  That *includes* any pushConstant: nil byte codes establishing temps
> in the block.  Instead, it is expected that "self method sourceNodeForPC:
> self startpc - 1" answers the same as "self method sourceNodeForPC: self
> blockCreationPC", where self blockCreationPC is the pc of the block's block
> creation bytecode.*
>
> *In Squeak we have*
> *BlockClosure>>blockCreationPC*
> * "Answer the pc for the bytecode that created the receuver."*
> * | method |*
> * method := self method.*
> * ^method encoderClass*
> * pcOfBlockCreationBytecodeForBlockStartingAt: startpc*
> * in: method*
>
> *This is because we support (as you will soon enough) different byte code
> sets so it is wrong to assume the size of the block creation bytecode is 4.*
> "
>
>
>>
>>>
>>> self method sourceNodeForPC: self startpc - 4
>>>
>>
>> We already have this little heuristic
>>
>> instructionForPC: aPC
>>   0 to: -3 by: -1 do: [ :off |
>>         (self firstInstructionMatching: [:ir | ir bytecodeOffset = (aPC -
>> off) ]) ifNotNil: [:it |^it]]
>>
>> AFAUI this 0 to -3 offset is used because we have 1,2,3 or 4 byte-length
>> bytecodes.
>>
>
> Well this will break down with the Sista byte code
>

I did not write that code, I just try to understand what I see.


> set because one could conceivably have 7 or 8 byte bytecoedes when one
> includes prefixes.  In the Newspeak and Sista sets we extend the ranges of
> byte codes by allowing prefixes.  Notionally the number of prefixes is
> unlimited but in practice we're using only one of each of the two prefix
> bytecodes Prefix A & Prefix B (currently E0 and E1 in all sets).
>
> But in the Sista set there is a field in the block creation byte code that
> reveals how many prefixes the byte code has so one can compute the actual
> start of the block creation byte code.  i.e.
>
> EncoderForSistaV1 class>>pcOfBlockCreationBytecodeForBlockStartingAt:
> startpc in: method
> "Answer the pc of the push closure bytecode whose block starts at startpc
> in method.
> May need to back up to include extension bytecodes."
>
> "* 224 11100000 aaaaaaaa Extend A (Ext A = Ext A prev * 256 + Ext A)
> * 225 11100001 bbbbbbbb Extend B (Ext B = Ext B prev * 256 + Ext B)
> ** 250 11111010 eeiiikkk jjjjjjjj Push Closure Num Copied iii
> (+ExtA//16*8) Num Args kkk (+ ExtA\\16*8) BlockSize jjjjjjjj (+ExtB*256).
> ee = num extensions"
> | numExtensions |
> self assert: (method at: startpc - 3) = 250.
> numExtensions := (method at: startpc - 2) >> 6.
> ^startpc - 3 - (numExtensions * 2)
>
> and make sure that the compiler maps a block creation bytecode to the
>>> source node for the entire block.
>>>
>>
>> in the above code (instructionForPC) we try to find the instruction for
>> the pc (here the pc of the closure creation code), but I don't really
>> understand what
>> "bytecodeOffset" is, it looks like (bytecodeIndex+startPC), but for a
>> IRPushClosureCopy, it looks like the bytecodeIndex does include
>> the number of local temps resp. (numberOfLocalTemps times the
>> bytecodelength for pushConstant:nil).
>>
>
> Marcus, what is bytecodeOffset?  Is it the distance from the first byte
> code or the distance from the first literal or...?
>
> The way to think about "self method sourceNodeForPC: self startpc - 1 +
>>> self numLocalTemps" not making sense is that a pc inside the block must map
>>> to a statement inside the block, not the block itself.
>>>
>>
>> Hm, I don't know :)
>>
>
> Why?  I designed the closure byte code set so I'm telling you :-).  It's
> safe to believe me.
>

I do believe, I just don't understand.


> For example, an initial pushConstant: nil byte code in a block either
> establishes the first local temp in that block, or is an argument of a send
> in the block.  In either case it refers to an element inside the block, not
> to the entire block itself.  the thing that defines the entire block is the
> block creation byte code, which includes the span (the size of) the block's
> bytecodes.  I chose to live with this annoying ambiguity because there were
> very few unused byte codes and I did;t want to use all of them for the
> closure byte code set.  And I chose the closure architecture so I could
> write a faster VM than one that accessed temps directly in outer scopes
> (which I go into at length on my blog).
>

I read it, but I don't understand how can calling
self method sourceNodeForPC: self startpc -1
depend on the pc inside the block? Isn't this only to get the sourceNode of
the block object?




>
> HTH
>>>
>>>
>>>>
>>>>
>>>>>
>>>>>         Marcus
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>
>>>
>>>
>>> --
>>> _,,,^..^,,,_
>>> best, Eliot
>>>
>>
>>
>
>
> --
> _,,,^..^,,,_
> best, Eliot
>

Reply via email to