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
