On Tue, Oct 14, 2014 at 11:15 AM, Nicolai Hess <[email protected]> wrote:

> Thank you eliot, marcus
>
> Yes I know your blog it is a great source of information.
> I am curious how the squeak compiler/debugger handles this (I'll look into
> it).
>

There's no scope at run-time, only at compile time.  AT compile time the
BlockNodes for optimized blocks get checked for the optimized selectors
(ifTrue: whileTrue and: et al) and have a flag set if they can be optimized
(have the right number of arguments).  At run-time there's no evidence of
an optimized block.  One is left in the enclosing method/block activation.

About opal and optimized block scope:
> Yes, I like the way this "special" non-scope is modelled with
> its own scope class.
> But somehow the whileTrue: receiver block is handled different than
> the ifTrue: block argument.
>

How so?  Is it the source extent that is wrong?

2014-10-14 17:41 GMT+02:00 Eliot Miranda <[email protected]>:
>
>> Hi Marcus,
>>
>> On Tue, Oct 14, 2014 at 4:09 AM, Marcus Denker <[email protected]>
>> wrote:
>>
>>>
>>> > On 12 Oct 2014, at 11:49, Nicolai Hess <[email protected]> wrote:
>>> >
>>> > I tried to solve issues
>>> > "13260 inspecting variables in the debugger fails in some cases" and
>>> > "14058 Inconsistent information in debugger"
>>> > and found some oddities in the way opal (compiler and the debuggermap)
>>> > handles tempory variables.
>>> > I am not sure if these are bugs.
>>> >
>>> > 1. order of temporaries:
>>> > Evaluating this method
>>> > |a b c|
>>> > a:=1.
>>> > b:=2.
>>> > c:=3.
>>> > thisContext tempNames logCr.
>>> > ["in a block ! " thisContext tempNames logCr . a+b+c ] value.
>>> >
>>> > prints in the transcript
>>> > #(#a #b #c)
>>> > #(#a #b #c)
>>> >
>>> > - ok, both contexts, the method and block context, use the same
>>> > ordering for the tempories
>>> >
>>> > writing on one variable in the block context require an indirection
>>> vector for
>>> > the variable
>>> >
>>> > |a b c|
>>> > a:=1.
>>> > b:=2.
>>> > c:=3.
>>> > thisContext tempNames logCr.
>>> > [b:=1. thisContext tempNames  logCr. a+b+c ] value.
>>> >
>>> > here the variable b is written within the block context. This method
>>> prints
>>> > #(#b #a #c)
>>> > #(#a #c #b)
>>> >
>>> > - strange the variable order has changed and is not the same in both
>>> contexts.
>>> >
>>>
>>> Yes, but behind the scenes a lot is going on… when you assign a variable
>>> in a block, this
>>> variable can not be allocated like a normal temp. There is instead an
>>> array (temp vector) allocated where this
>>> variable lives. Then *this array* has a “temp” and is accessed in the
>>> block like the variables
>>> in the case of no assignment.
>>>
>>
>> Niolai, you're probably aware of it but there's an extensive write up of
>> the design on my blog:
>>
>> http://www.mirandabanda.org/cogblog/2008/06/07/closures-part-i/
>>
>> http://www.mirandabanda.org/cogblog/2008/07/22/closures-part-ii-the-bytecodes/
>>
>> http://www.mirandabanda.org/cogblog/2008/07/24/closures-part-iii-the-compiler/
>>  (especially
>> section "The Closure Analysis")
>>
>> This means that there can not be an order: some variables live in arrays,
>>> others in the context.
>>> The only thing that you have is a scope that nows how a name maps to a
>>> specific offset or two
>>> (offset of temp of the “temp vector + offset inside this temp vector).
>>>
>>
>> I disagree slightly.  The Squeak compiler maintains order, both in temps
>> and in indirect temps.  But whether a temp is direct or indirect depends on
>> a simple analysis of a single method.  I still think it is part of the
>> Smalltalk culture to KISS and e.g. maintain the order of temps.
>>
>> One could beautify it a bit by sorting the names according to the
>>> original definition order, though.
>>> (we should look onto that).
>>>
>>
>> The current exception system needs to access temps, e.g. ensure:'s and
>> ifCurtailed:'s complete and on:do:'s handlerActive.  Isn't it really
>> important to maintain ordering?  It certainly makes introspection easier.
>> One can go through a name-based interface but that is likely to be much
>> much slower in what is a perfrmance-critical part of the system.
>>
>>
>>>
>>> But even if we do, this does not mean that b has offset 2 in the
>>> example, as it lives in an array...
>>>
>>
>> Right.
>>
>>
>>>
>>>
>>> > 2. OCOptimizedBlockScope
>>> >
>>> > Consider a whileTrue: call
>>> > ["A-Block"] whileTrue:["B-Block"]
>>> > or an ifTrue:
>>> > ("some boolean value") ifTrue:["C-Block"]
>>> > stepping into the blocks with the debugger and reading the
>>> > values for a tempoariy variable shows that every block has
>>> > an OCOpotimizedBlockScope as its scope.
>>> > Are all  3 blocks the same kind of "optimized blocks"? because ->
>>> >
>>> Yes, we tried two ideas
>>> The first move only real existing scopes, that means, instead of an
>>> optimised scope
>>> point to the scope that all these optimized blocks are flattened into.
>>> But that was not nice and we could not get it to work.
>>> Instead, we opted into modelling the concept of  the optimised scope: on
>>> the AST
>>> level, the block has a scope (like all blocks), but when you add an
>>> entry (or query),
>>> it will forward to the “real” existing scope.
>>>
>>> I still like it, it makes things very explicit.
>>>
>>> > 3. Blocks within optimized blocks
>>> > This method prints the number of tempories on the Transcript
>>> > (the on:do: call is just a dummy for an "block within a block"
>>> > but the important part is the usage of the three variables
>>> > in the do-block)
>>> >
>>> > |a b c|
>>> > a:=1.
>>> > b:=2.
>>> > c:=3.
>>> > (c>0) ifTrue:[
>>> >     [ a asString ] on:Error do:[:ex | a value:a value:b value:c].
>>> > ].
>>> > thisContext method numTemps logCr.
>>> > a
>>> >
>>> > The output on the transcript is "3"
>>> > - ok
>>> >
>>> > This method is like the one above, but the nested block
>>> > is in the receiver of the whileTrue:[] call (again, an optimized
>>> block, right?)
>>> >
>>> > |a b c|
>>> > a:=1.
>>> > b:=2.
>>> > c:=3.
>>> >
>>> > [
>>> >     [ a asString ] on:Error do:[:ex | a value:a value:b value:c].
>>> >      c <0 ] whileTrue:[].
>>> > thisContext method numTemps logCr.
>>> > a
>>> >
>>> > The output on the Transcript is "1"
>>> > And it depends on the number of used variables in the do-Block
>>> > The same method but with the do-Block
>>> > do:[:ex | a value:a value:b]
>>> > would print 2 as number of temporaries.
>>> >
>>>
>>>
>>> Hmm… I need to think about this one. It looks strange, yes.
>>>
>>>         Marcus
>>>
>>>
>>>
>>>
>>>
>>
>>
>> --
>> best,
>> Eliot
>>
>
>


-- 
best,
Eliot

Reply via email to