Pharo-dev
By thread
pharo-dev@lists.pharo.org
By month
Messages by month
- ----- 2026 -----
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
August 2011
- 104 participants
- 1359 messages
Re: [Pharo-project] Some bugs
by Stéphane Ducasse
thanks a lot nicolas
It seems to work on my image too. I adding it to the bug entry.
What is great is that tomorrow I will be able to follow your path in the train.
Stef
On Aug 25, 2011, at 9:12 PM, Nicolas Cellier wrote:
> And by changing last line of this piece of code in #transformToDo:
> test := MessageNode new
> receiver: blockVar
> selector: (increment key > 0 ifTrue:
> [#<=] ifFalse: [#>=])
> arguments: (Array with: limit)
> precedence: precedence from: encoder
> sourceRange: (myRange first to: blockRange last).
> I get a "correct" selection...
>
> Nicolas
>
>
> 2011/8/25 Nicolas Cellier <nicolas.cellier.aka.nice(a)gmail.com>:
>> A few more notes:
>>
>> - Encoder>>rawSourceRanges answer a mapping AST Node -> sourceRange
>> Gnerally, I would expect sourceRange to be an Interval, but this has
>> to be confirmed.
>> Theses ranges are constructed at source code Parse time (see senders
>> of #noteSourceRange:forNode:)
>> - The program counters are assigned to AST nodes at byte code #generate time
>> - for inlined macros, like #to:do: in our case, this pc is after the
>> initialize and test statements.
>>
>> in CompiledMethod>>#rawSourceRangesAndMethodDo:
>> I just evaluated this:
>>
>> methNode encoder rawSourceRanges collect: [:ival |
>> sourceText copyFrom: ival first to: ival last]
>>
>> And what I see is that the original to:do: message (before macros
>> inlining) has the right range
>> {1
>> to: 5
>> do: [:index |
>> temp := index.
>> collection
>> add: [temp]]}->a Text for 'to: 5 do: [ :index |
>> temp := index.
>> collection add: [ temp ] ]'
>> This node is the original #to:do: and has pc=42
>>
>> There is also
>> {a LeafNode}->a Text for '[ :index |
>> temp := index.
>> collection add: [ temp ] ]'
>> which has a nil pc so it won't be taken into account in the source map.
>>
>> But one of the messages produced by the inlining has this curious range:
>> {index <= 5}->a Text for 'to: 5 do: [ :index |
>> temp := index.
>> c'
>> This node has pc = 40, so it will be selected before the correct one
>> above has a chance to be.
>> {index <= 5} is the test statement produced by inlining, and this
>> seems to be the incorrect highlighting we see.
>> Thus we know we have to concentrate on macro inlining.
>> This happens in MessageNode>>transformToDo:
>> We'll see this.
>>
>> In the interim, I played with eliminating the nodes having unitilialized pc
>> Let us try to evaluate this snippet in debugger's inspector:
>> (methNode encoder rawSourceRanges keys select: [:e | e pc > 0])
>> collect: [:node |
>> | ival |
>> ival := methNode encoder rawSourceRanges at: node.
>> node -> (sourceText copyFrom: ival first to: ival last)]
>>
>> Oh god, a bug in the debugger:
>> DoItIn: homeContext
>> ^ ((homeContext namedTempAt: 2) encoder rawSourceRanges keys
>> select: [:e | e pc > 0])
>> collect: [:node |
>> | ival |
>> ival := (node namedTempAt: 2) encoder rawSourceRanges at: node.
>> node
>> -> (sourceText copyFrom: ival first to: ival last)]
>> (node namedTempAt: 2) does not mean a thing...
>> A confusion occurred between the homeContext (DoItIn: method argument)
>> and node (the block argument)
>> Nevermind... forget about it.
>>
>> Now let's just concentrate on MessageNode>>transformToDo:
>> We see this code:
>> test := MessageNode new
>> receiver: blockVar
>> selector: (increment key > 0 ifTrue: [#<=] ifFalse: [#>=])
>> arguments: (Array with: limit)
>> precedence: precedence from: encoder
>> sourceRange: (myRange first to: blockRange first).
>>
>> So the intention seems to select 'to: 5 do: '
>>
>> But we see this:
>> BlockNode>>noteSourceRangeStart:end:encoder:
>> "Note two source ranges for this node. One is for the debugger
>> and is of the last expression, the result of the block. One is for
>> source analysis and is for the entire block."
>> encoder
>> noteSourceRange: (start to: end)
>> forNode: self closureCreationNode.
>> startOfLastStatement
>> ifNil:
>> [encoder
>> noteSourceRange: (start to: end)
>> forNode: self]
>> ifNotNil:
>> [encoder
>> noteSourceRange: (startOfLastStatement to: end - 1)
>> forNode: self]
>>
>> So it seems intentional to select only the last instruction of the
>> block for the debugger.
>> We'd better not change this without prior asking Eliot.
>> But obviously, this is not what is expected by the #transformToDo:
>>
>> Nicolas
>>
>> 2011/8/25 Stéphane Ducasse <stephane.ducasse(a)inria.fr>:
>>> tx nicolas this is a cool way to help :)
>>>
>>> Stef
>>>
>>> On Aug 24, 2011, at 9:54 PM, Nicolas Cellier wrote:
>>>
>>>> So the entries of interest for highlighting are
>>>>
>>>> Debugger>>contentsSelection
>>>> Debugger>>pcRange
>>>> CompiledMethod>>debuggerMap
>>>> DebuggerMethodMap class>>forMethod:
>>>> DebuggerMethodMap>>rangeForPC:contextIsActiveContext:
>>>>
>>>> Then you see the DebuggerMethodMap>>forMethod:methodNode: takes both a
>>>> CompiledMethod and its #methodNode.
>>>> CompiledMethod>>methodNode invokes the Parser to get the
>>>> AbstractSyntaxTree from method source, and if it ever fails ends up by
>>>> trying to decompile the byteCodes.
>>>>
>>>> This is the easy part. Now we to deal with #abstractPCForConcretePC:
>>>> and #abstractSourceMap.
>>>>
>>>> By reading CompiledMethod>>abstractPCForConcretePC: you should quickly
>>>> understand that a concrete PC is a byte offset of current byteCode
>>>> (the offsets displayed in the byteCode view) while the abstractPC is
>>>> just the rank of current byteCode in the list of byteCodes
>>>> instructions composing the CompiledMethod. This is just because
>>>> "byteCodes" may spread on several bytes beside their name...
>>>> This will use InstructionStream and InstructionClient which are just
>>>> an iterator and a sort of visitor on byteCode instructions.
>>>> So this is not really interesting.
>>>>
>>>> The more interesting part is #abstractSourceMap
>>>> There is a first step to obtain CompiledMethod>>rawSourceRangesAndMethodDo:
>>>> This is the most important part.
>>>> The rest is again a mapping from concretePC (instruction byte offset)
>>>> to abstractPC (instruction rank).
>>>> And some build of a dictionary mapping instruction rank (abstractPC)
>>>> -> selected range.
>>>>
>>>> Note that the last trick seems to use a regenerated CompiledMethod
>>>> (theMethodToScan) rather than the original CompiledMethod. There is no
>>>> assertion whether these two are equivalent or not. A priori, they
>>>> should, unless the Compiler changed since last compilation or if its
>>>> behaviour is affected by some Preferences... Would we introduce some
>>>> customizable Compiler optimizations that this could become a problem
>>>> (We would then add to map decompiled AST to source code AST, probably
>>>> with guesses, unless the CompiledMethod would contain debugger
>>>> friendly hints...)
>>>> We will consider this is not a problem by now.
>>>>
>>>> So let's now concentrate on rawSourceRangesAndMethodDo:
>>>> The nice thing is that you now can just debug this
>>>>
>>>> (ClosureTests>>#testToDoOutsideTemp) methodNode
>>>> rawSourceRangesAndMethodDo: [:rs :mth | ]
>>>>
>>>> and see how it goes in Squeak. I did not look in Pharo yet, but I
>>>> would be amazed to see it much different.
>>>> It's now late, and my spare time is off, but you have clues to get
>>>> more insights. I wish you good debugging, and come back to me if it
>>>> ever goes in deeper complications.
>>>>
>>>> Cheers
>>>>
>>>> Nicolas
>>>>
>>>> 2011/8/24 Michael Roberts <mike(a)mjr104.co.uk>:
>>>>>
>>>>>>
>>>>>> Ok I'm curious to know then.
>>>>>
>>>>> Here is a little trace from this example method:
>>>>>
>>>>> toDoOutsideTemp
>>>>> | temp collection |
>>>>> collection := OrderedCollection new.
>>>>> 1 to: 5 do: [ :index |
>>>>> temp := index.
>>>>> collection add: [ temp ] ]
>>>>>
>>>>> Trace is start,stop position of the highlight for each 'step over'.
>>>>>
>>>>> Whilst the numbers are hard to visualise, below you can see how they
>>>>> slightly diverge.
>>>>> Left Pharo Right Squeak
>>>>>
>>>>> 50, 73 71, 73 diff
>>>>> 71, 73 71, 73
>>>>> 50, 73 50, 73
>>>>> 108, 115 79, 121 diff
>>>>> 79, 121 79, 121
>>>>> 108, 115 108, 115
>>>>> 132, 144 132, 144
>>>>> 147, 146 146, 146 (diff negative size means no highlight)
>>>>> 146, 146 146, 146
>>>>> 79, 121 79, 121
>>>>> 108, 115 108, 115
>>>>> 132, 144 132, 144
>>>>> 147, 146 146, 146
>>>>> 146, 146 146, 146
>>>>> 79, 121 79, 121
>>>>> 108, 115 108, 115
>>>>> 132, 144 132, 144
>>>>> 147, 146 146, 146
>>>>> 146, 146 146, 146
>>>>> 79, 121 79, 121
>>>>> 108, 115 108, 115
>>>>> etc...
>>>>> For example the first difference is because Pharo shows the whole assignment
>>>>> of the first line as the first send, even though it is not.
>>>>> The second difference is that Pharo shows the assignment inside the block as
>>>>> the first highlight of the loop even though the to:do should be
>>>>> highlighted....but both Pharo & Squeak get the to:do: wrong when they choose
>>>>> to show it.
>>>>> hope you get the idea...
>>>>> Mike
>>>>
>>>
>>>
>>>
>>
>
Aug. 25, 2011
Re: [Pharo-project] Filesystem in collab book
by Stéphane Ducasse
Thanks.
Max did you see the chapter in the new pharo book on git?
Because I should do a pass on it but anybody is welcome.
Stef
On Aug 25, 2011, at 8:38 PM, Max Leske wrote:
> I wrote a few lines on Filesystem in the collab book: http://book.pharo-project.org/book/PharoTools/Filesystem/
>
> Please take a look and let me know if you'd like to see any changes.
>
> Cheers,
> Max
Aug. 25, 2011
Re: [Pharo-project] Some bugs
by Nicolas Cellier
And by changing last line of this piece of code in #transformToDo:
test := MessageNode new
receiver: blockVar
selector: (increment key > 0 ifTrue:
[#<=] ifFalse: [#>=])
arguments: (Array with: limit)
precedence: precedence from: encoder
sourceRange: (myRange first to: blockRange last).
I get a "correct" selection...
Nicolas
2011/8/25 Nicolas Cellier <nicolas.cellier.aka.nice(a)gmail.com>:
> A few more notes:
>
> - Encoder>>rawSourceRanges answer a mapping AST Node -> sourceRange
> Â Gnerally, I would expect sourceRange to be an Interval, but this has
> to be confirmed.
> Â Theses ranges are constructed at source code Parse time (see senders
> of #noteSourceRange:forNode:)
> - The program counters are assigned to AST nodes at byte code #generate time
> - for inlined macros, like #to:do: in our case, this pc is after the
> initialize and test statements.
>
> in CompiledMethod>>#rawSourceRangesAndMethodDo:
> I just evaluated this:
>
> methNode encoder rawSourceRanges collect: [:ival |
> Â Â Â Â sourceText copyFrom: ival first to: ival last]
>
> And what I see is that the original to:do: message (before macros
> inlining) has the right range
> {1
> Â Â Â Â to: 5
> Â Â Â Â do: [:index |
> Â Â Â Â Â Â Â Â temp := index.
> Â Â Â Â Â Â Â Â collection
> Â Â Â Â Â Â Â Â Â Â Â Â add: [temp]]}->a Text for 'to: 5 do: [ :index |
> Â Â Â Â Â Â Â Â temp := index.
> Â Â Â Â Â Â Â Â collection add: [ temp ] ]'
> This node is the original #to:do: and has pc=42
>
> There is also
> {a LeafNode}->a Text for '[ :index |
> Â Â Â Â Â Â Â Â temp := index.
> Â Â Â Â Â Â Â Â collection add: [ temp ] ]'
> which has a nil pc so it won't be taken into account in the source map.
>
> But one of the messages produced by the inlining has this curious range:
> {index <= 5}->a Text for 'to: 5 do: [ :index |
> Â Â Â Â Â Â Â Â temp := index.
> Â Â Â Â Â Â Â Â c'
> This node has pc = 40, so it will be selected before the correct one
> above has a chance to be.
> {index <= 5} is the test statement produced by inlining, and this
> seems to be the incorrect highlighting we see.
> Thus we know we have to concentrate on macro inlining.
> This happens in MessageNode>>transformToDo:
> We'll see this.
>
> In the interim, I played with eliminating the nodes having unitilialized pc
> Let us try to evaluate this snippet in debugger's inspector:
> (methNode encoder rawSourceRanges keys select: [:e | e pc > 0])
> collect: [:node |
> Â Â Â Â | ival |
> Â Â Â Â ival := methNode encoder rawSourceRanges at: node.
> Â Â Â Â node -> (sourceText copyFrom: ival first to: ival last)]
>
> Oh god, a bug in the debugger:
> DoItIn: homeContext
> Â Â Â Â ^ ((homeContext namedTempAt: 2) encoder rawSourceRanges keys
> Â Â Â Â Â Â Â Â select: [:e | e pc > 0])
> Â Â Â Â Â Â Â Â collect: [:node |
> Â Â Â Â Â Â Â Â Â Â Â Â | ival |
> Â Â Â Â Â Â Â Â Â Â Â Â ival := (node namedTempAt: 2) encoder rawSourceRanges at: node.
> Â Â Â Â Â Â Â Â Â Â Â Â node
> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â -> (sourceText copyFrom: ival first to: ival last)]
> (node namedTempAt: 2) does not mean a thing...
> A confusion occurred between the homeContext (DoItIn: method argument)
> and node (the block argument)
> Nevermind... forget about it.
>
> Now let's just concentrate on MessageNode>>transformToDo:
> We see this code:
> Â Â Â Â test := MessageNode new
> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â receiver: blockVar
> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â selector: (increment key > 0 ifTrue: [#<=] ifFalse: [#>=])
> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â arguments: (Array with: limit)
> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â precedence: precedence from: encoder
> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â sourceRange: (myRange first to: blockRange first).
>
> So the intention seems to select 'to: 5 do: '
>
> But we see this:
> BlockNode>>noteSourceRangeStart:end:encoder:
> Â Â Â Â "Note two source ranges for this node. Â One is for the debugger
> Â Â Â Â and is of the last expression, the result of the block. Â One is for
> Â Â Â Â source analysis and is for the entire block."
> Â Â Â Â encoder
> Â Â Â Â Â Â Â Â noteSourceRange: (start to: end)
> Â Â Â Â Â Â Â Â forNode: self closureCreationNode.
> Â Â Â Â startOfLastStatement
> Â Â Â Â Â Â Â Â ifNil:
> Â Â Â Â Â Â Â Â Â Â Â Â [encoder
> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â noteSourceRange: (start to: end)
> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â forNode: self]
> Â Â Â Â Â Â Â Â ifNotNil:
> Â Â Â Â Â Â Â Â Â Â Â Â [encoder
> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â noteSourceRange: (startOfLastStatement to: end - 1)
> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â forNode: self]
>
> So it seems intentional to select only the last instruction of the
> block for the debugger.
> We'd better not change this without prior asking Eliot.
> But obviously, this is not what is expected by the #transformToDo:
>
> Nicolas
>
> 2011/8/25 Stéphane Ducasse <stephane.ducasse(a)inria.fr>:
>> tx nicolas this is a cool way to help :)
>>
>> Stef
>>
>> On Aug 24, 2011, at 9:54 PM, Nicolas Cellier wrote:
>>
>>> So the entries of interest for highlighting are
>>>
>>> Debugger>>contentsSelection
>>> Debugger>>pcRange
>>> CompiledMethod>>debuggerMap
>>> DebuggerMethodMap class>>forMethod:
>>> DebuggerMethodMap>>rangeForPC:contextIsActiveContext:
>>>
>>> Then you see the DebuggerMethodMap>>forMethod:methodNode: takes both a
>>> CompiledMethod and its #methodNode.
>>> CompiledMethod>>methodNode invokes the Parser to get the
>>> AbstractSyntaxTree from method source, and if it ever fails ends up by
>>> trying to decompile the byteCodes.
>>>
>>> This is the easy part. Now we to deal with #abstractPCForConcretePC:
>>> and #abstractSourceMap.
>>>
>>> By reading CompiledMethod>>abstractPCForConcretePC: you should quickly
>>> understand that a concrete PC is a byte offset of current byteCode
>>> (the offsets displayed in the byteCode view) while the abstractPC is
>>> just the rank of current byteCode in the list of byteCodes
>>> instructions composing the CompiledMethod. This is just because
>>> "byteCodes" may spread on several bytes beside their name...
>>> This will use InstructionStream and InstructionClient which are just
>>> an iterator and a sort of visitor on byteCode instructions.
>>> So this is not really interesting.
>>>
>>> The more interesting part is #abstractSourceMap
>>> There is a first step to obtain CompiledMethod>>rawSourceRangesAndMethodDo:
>>> This is the most important part.
>>> The rest is again a mapping from concretePC (instruction byte offset)
>>> to abstractPC (instruction rank).
>>> And some build of a dictionary mapping instruction rank (abstractPC)
>>> -> selected range.
>>>
>>> Note that the last trick seems to use a regenerated CompiledMethod
>>> (theMethodToScan) rather than the original CompiledMethod. There is no
>>> assertion whether these two are equivalent or not. A priori, they
>>> should, unless the Compiler changed since last compilation or if its
>>> behaviour is affected by some Preferences... Would we introduce some
>>> customizable Compiler optimizations that this could become a problem
>>> (We would then add to map decompiled AST to source code AST, probably
>>> with guesses, unless the CompiledMethod would contain debugger
>>> friendly hints...)
>>> We will consider this is not a problem by now.
>>>
>>> So let's now concentrate on rawSourceRangesAndMethodDo:
>>> The nice thing is that you now can just debug this
>>>
>>> (ClosureTests>>#testToDoOutsideTemp) methodNode
>>> rawSourceRangesAndMethodDo: [:rs :mth | ]
>>>
>>> and see how it goes in Squeak. I did not look in Pharo yet, but I
>>> would be amazed to see it much different.
>>> It's now late, and my spare time is off, but you have clues to get
>>> more insights. I wish you good debugging, and come back to me if it
>>> ever goes in deeper complications.
>>>
>>> Cheers
>>>
>>> Nicolas
>>>
>>> 2011/8/24 Michael Roberts <mike(a)mjr104.co.uk>:
>>>>
>>>>>
>>>>> Ok I'm curious to know then.
>>>>
>>>> Here is a little trace from this example method:
>>>>
>>>> toDoOutsideTemp
>>>> | temp collection |
>>>> collection := OrderedCollection new.
>>>> 1 to: 5 do: [ :index |
>>>> temp := index.
>>>> collection add: [ temp ] ]
>>>>
>>>> Trace is start,stop position of the highlight for each 'step over'.
>>>>
>>>> Whilst the numbers are hard to visualise, below you can see how they
>>>> slightly diverge.
>>>> Left Pharo  Right  Squeak
>>>>
>>>> 50, 73 Â Â 71, 73 Â Â Â diff
>>>> 71, 73 Â Â 71, 73
>>>> 50, 73 Â Â 50, 73
>>>> 108, 115 Â 79, 121 Â Â Â diff
>>>> 79, 121 Â Â 79, 121
>>>> 108, 115 Â 108, 115
>>>> 132, 144 Â 132, 144
>>>> 147, 146 Â 146, 146 Â Â (diff negative size means no highlight)
>>>> 146, 146 Â 146, 146
>>>> 79, 121 Â Â 79, 121
>>>> 108, 115 Â 108, 115
>>>> 132, 144 Â 132, 144
>>>> 147, 146 Â 146, 146
>>>> 146, 146 Â 146, 146
>>>> 79, 121 Â Â 79, 121
>>>> 108, 115 Â 108, 115
>>>> 132, 144 Â 132, 144
>>>> 147, 146 Â 146, 146
>>>> 146, 146 Â 146, 146
>>>> 79, 121 Â Â 79, 121
>>>> 108, 115 Â 108, 115
>>>> etc...
>>>> For example the first difference is because Pharo shows the whole assignment
>>>> of the first line as the first send, even though it is not.
>>>> The second difference is that Pharo shows the assignment inside the block as
>>>> the first highlight of the loop even though the to:do should be
>>>> highlighted....but both Pharo & Squeak get the to:do: wrong when they choose
>>>> to show it.
>>>> hope you get the idea...
>>>> Mike
>>>
>>
>>
>>
>
Aug. 25, 2011
Re: [Pharo-project] Some bugs
by Nicolas Cellier
A few more notes:
- Encoder>>rawSourceRanges answer a mapping AST Node -> sourceRange
Gnerally, I would expect sourceRange to be an Interval, but this has
to be confirmed.
Theses ranges are constructed at source code Parse time (see senders
of #noteSourceRange:forNode:)
- The program counters are assigned to AST nodes at byte code #generate time
- for inlined macros, like #to:do: in our case, this pc is after the
initialize and test statements.
in CompiledMethod>>#rawSourceRangesAndMethodDo:
I just evaluated this:
methNode encoder rawSourceRanges collect: [:ival |
sourceText copyFrom: ival first to: ival last]
And what I see is that the original to:do: message (before macros
inlining) has the right range
{1
to: 5
do: [:index |
temp := index.
collection
add: [temp]]}->a Text for 'to: 5 do: [ :index |
temp := index.
collection add: [ temp ] ]'
This node is the original #to:do: and has pc=42
There is also
{a LeafNode}->a Text for '[ :index |
temp := index.
collection add: [ temp ] ]'
which has a nil pc so it won't be taken into account in the source map.
But one of the messages produced by the inlining has this curious range:
{index <= 5}->a Text for 'to: 5 do: [ :index |
temp := index.
c'
This node has pc = 40, so it will be selected before the correct one
above has a chance to be.
{index <= 5} is the test statement produced by inlining, and this
seems to be the incorrect highlighting we see.
Thus we know we have to concentrate on macro inlining.
This happens in MessageNode>>transformToDo:
We'll see this.
In the interim, I played with eliminating the nodes having unitilialized pc
Let us try to evaluate this snippet in debugger's inspector:
(methNode encoder rawSourceRanges keys select: [:e | e pc > 0])
collect: [:node |
| ival |
ival := methNode encoder rawSourceRanges at: node.
node -> (sourceText copyFrom: ival first to: ival last)]
Oh god, a bug in the debugger:
DoItIn: homeContext
^ ((homeContext namedTempAt: 2) encoder rawSourceRanges keys
select: [:e | e pc > 0])
collect: [:node |
| ival |
ival := (node namedTempAt: 2) encoder rawSourceRanges at: node.
node
-> (sourceText copyFrom: ival first to: ival last)]
(node namedTempAt: 2) does not mean a thing...
A confusion occurred between the homeContext (DoItIn: method argument)
and node (the block argument)
Nevermind... forget about it.
Now let's just concentrate on MessageNode>>transformToDo:
We see this code:
test := MessageNode new
receiver: blockVar
selector: (increment key > 0 ifTrue: [#<=] ifFalse: [#>=])
arguments: (Array with: limit)
precedence: precedence from: encoder
sourceRange: (myRange first to: blockRange first).
So the intention seems to select 'to: 5 do: '
But we see this:
BlockNode>>noteSourceRangeStart:end:encoder:
"Note two source ranges for this node. One is for the debugger
and is of the last expression, the result of the block. One is for
source analysis and is for the entire block."
encoder
noteSourceRange: (start to: end)
forNode: self closureCreationNode.
startOfLastStatement
ifNil:
[encoder
noteSourceRange: (start to: end)
forNode: self]
ifNotNil:
[encoder
noteSourceRange: (startOfLastStatement to: end - 1)
forNode: self]
So it seems intentional to select only the last instruction of the
block for the debugger.
We'd better not change this without prior asking Eliot.
But obviously, this is not what is expected by the #transformToDo:
Nicolas
2011/8/25 Stéphane Ducasse <stephane.ducasse(a)inria.fr>:
> tx nicolas this is a cool way to help :)
>
> Stef
>
> On Aug 24, 2011, at 9:54 PM, Nicolas Cellier wrote:
>
>> So the entries of interest for highlighting are
>>
>> Debugger>>contentsSelection
>> Debugger>>pcRange
>> CompiledMethod>>debuggerMap
>> DebuggerMethodMap class>>forMethod:
>> DebuggerMethodMap>>rangeForPC:contextIsActiveContext:
>>
>> Then you see the DebuggerMethodMap>>forMethod:methodNode: takes both a
>> CompiledMethod and its #methodNode.
>> CompiledMethod>>methodNode invokes the Parser to get the
>> AbstractSyntaxTree from method source, and if it ever fails ends up by
>> trying to decompile the byteCodes.
>>
>> This is the easy part. Now we to deal with #abstractPCForConcretePC:
>> and #abstractSourceMap.
>>
>> By reading CompiledMethod>>abstractPCForConcretePC: you should quickly
>> understand that a concrete PC is a byte offset of current byteCode
>> (the offsets displayed in the byteCode view) while the abstractPC is
>> just the rank of current byteCode in the list of byteCodes
>> instructions composing the CompiledMethod. This is just because
>> "byteCodes" may spread on several bytes beside their name...
>> This will use InstructionStream and InstructionClient which are just
>> an iterator and a sort of visitor on byteCode instructions.
>> So this is not really interesting.
>>
>> The more interesting part is #abstractSourceMap
>> There is a first step to obtain CompiledMethod>>rawSourceRangesAndMethodDo:
>> This is the most important part.
>> The rest is again a mapping from concretePC (instruction byte offset)
>> to abstractPC (instruction rank).
>> And some build of a dictionary mapping instruction rank (abstractPC)
>> -> selected range.
>>
>> Note that the last trick seems to use a regenerated CompiledMethod
>> (theMethodToScan) rather than the original CompiledMethod. There is no
>> assertion whether these two are equivalent or not. A priori, they
>> should, unless the Compiler changed since last compilation or if its
>> behaviour is affected by some Preferences... Would we introduce some
>> customizable Compiler optimizations that this could become a problem
>> (We would then add to map decompiled AST to source code AST, probably
>> with guesses, unless the CompiledMethod would contain debugger
>> friendly hints...)
>> We will consider this is not a problem by now.
>>
>> So let's now concentrate on rawSourceRangesAndMethodDo:
>> The nice thing is that you now can just debug this
>>
>> (ClosureTests>>#testToDoOutsideTemp) methodNode
>> rawSourceRangesAndMethodDo: [:rs :mth | ]
>>
>> and see how it goes in Squeak. I did not look in Pharo yet, but I
>> would be amazed to see it much different.
>> It's now late, and my spare time is off, but you have clues to get
>> more insights. I wish you good debugging, and come back to me if it
>> ever goes in deeper complications.
>>
>> Cheers
>>
>> Nicolas
>>
>> 2011/8/24 Michael Roberts <mike(a)mjr104.co.uk>:
>>>
>>>>
>>>> Ok I'm curious to know then.
>>>
>>> Here is a little trace from this example method:
>>>
>>> toDoOutsideTemp
>>> | temp collection |
>>> collection := OrderedCollection new.
>>> 1 to: 5 do: [ :index |
>>> temp := index.
>>> collection add: [ temp ] ]
>>>
>>> Trace is start,stop position of the highlight for each 'step over'.
>>>
>>> Whilst the numbers are hard to visualise, below you can see how they
>>> slightly diverge.
>>> Left Pharo  Right  Squeak
>>>
>>> 50, 73 Â Â 71, 73 Â Â Â diff
>>> 71, 73 Â Â 71, 73
>>> 50, 73 Â Â 50, 73
>>> 108, 115 Â 79, 121 Â Â Â diff
>>> 79, 121 Â Â 79, 121
>>> 108, 115 Â 108, 115
>>> 132, 144 Â 132, 144
>>> 147, 146 Â 146, 146 Â Â (diff negative size means no highlight)
>>> 146, 146 Â 146, 146
>>> 79, 121 Â Â 79, 121
>>> 108, 115 Â 108, 115
>>> 132, 144 Â 132, 144
>>> 147, 146 Â 146, 146
>>> 146, 146 Â 146, 146
>>> 79, 121 Â Â 79, 121
>>> 108, 115 Â 108, 115
>>> 132, 144 Â 132, 144
>>> 147, 146 Â 146, 146
>>> 146, 146 Â 146, 146
>>> 79, 121 Â Â 79, 121
>>> 108, 115 Â 108, 115
>>> etc...
>>> For example the first difference is because Pharo shows the whole assignment
>>> of the first line as the first send, even though it is not.
>>> The second difference is that Pharo shows the assignment inside the block as
>>> the first highlight of the loop even though the to:do should be
>>> highlighted....but both Pharo & Squeak get the to:do: wrong when they choose
>>> to show it.
>>> hope you get the idea...
>>> Mike
>>
>
>
>
Aug. 25, 2011
[Pharo-project] Filesystem in collab book
by Max Leske
I wrote a few lines on Filesystem in the collab book: http://book.pharo-project.org/book/PharoTools/Filesystem/
Please take a look and let me know if you'd like to see any changes.
Cheers,
Max
Aug. 25, 2011
[Pharo-project] The serverMode flag and some thoughts on event polling
by Dimitry Golubovsky
Hi,
[this is not really about VM alone, but rather how image and VM
interact - hence posting to multiple lists]
In the process of porting Cog to Android, I observed the following
pattern. If a scrollbar's "up" or "down" button is held pressed
(prolonged tap on a button) for few seconds, the VM freezes, and gets
killed by Android. Digging down the code got me to the
WorldState>>interCyclePause: method. When there are morphs requesting
stepping by shorter than certain time interval, the process
responsibke for running step methods keeps looping without giving up
to lower priority processes (and the host OS). ScrollBar seems to
decrease the stepping interval over time to simulate accelerated
scrolling.
In order to port Cog to Android, I turned it into an event-driven VM
based on ideas found in [1]. The same was done by Andreas for his
earlier Classic VM port. My approach is a bit different such as the
longjmp call is made as part of the relinquishProcessor primitive.
Such primitive is called only from the lowest priority (idle) process
which only can run when there are no external events to deal with. The
event-driven VM needs to exit from the interpreter to the host process
in order to obtain any input events. Thus, non-interrupted polling
just deadlocks the interpreter as it cannot exit to the host process
to get more events, yet keeps polling for them.
The serverMode flag [2] (aka Mantis #6581) came to rescue. With such
flag set to true, polling for events always yields CPU for 50ms (which
in the Android case is meaningless anyway: I would not give the VM
idle timer more often than 10 times per sec, so 50ms granularity is
just not handleable). Anyway this does the trick as the lowest
priority process gets its CPU time, and exits the interpreter to the
host process. With serverMode = true I can tap a scroller button as
long as I want, and even the text cursor in a workspace keeps blinking
which means that stepping works and VM is alive. BTW in Android, the
interpreter will be called as soon as any user action is intercepted,
so responsiveness is not degraded regardless of the delay introduced
by serverMode.
I have found at least one place (this is in PharoCore) where
serverMode is not honored: PolygonMorph class >> fromHand: (this
method creates a polygon drawn by the mouse)
This method has code pieces (repeating multiple times btw - why is it
not a separate method?)
[Sensor anyButtonPressed] whileFalse:
[self currentWorld displayWorldSafely; runStepMethods].
which is clearly grabbing the event sensor to the polygon morph while
keeping other morphs stepped, so the VM does not seem dead entirely.
In my case though executing PolygonMorph fromHand: defaultHand freezes
the VM immediately as this is uninterrupted polling again.
While I'll try to experiment with inserting interCyclePause somewhere
in these loops, there are broader questions on how event polling is
done these days:
1. Are there other morphs in packages not included in PharoCore where
event grabbing is done such way?
1a. Is this possible in general to have such functionality properly
embedded in WorldState instead of having it in a morph itself, if
event grabbing is needed?
2. Are there images in active development (other than PharoCore, and
Squeak) where event polling is done without an option to relinquish
processor?
In fact, this VM freezing on stepping morphs was a big issue, and it
mainly kept me from moving towards the public release. Now that it
seems to be solved (unless there is a flaw in my logic above) it takes
me closer to finishing the Cog for Android port.
Thanks.
------------------------------------------
[1] http://lists.squeakfoundation.org/pipermail/vm-dev/2009-November/003385.html
[2] http://bugs.squeak.org/view.php?id=6581
--
Dimitry Golubovsky
Anywhere on the Web
Aug. 25, 2011
Re: [Pharo-project] [Vm-dev] Cog in Jenkis has brokken finalization
by Marcus Denker
On Aug 25, 2011, at 5:34 PM, Igor Stasenko wrote:
> On 25 August 2011 14:38, Mariano Martinez Peck <marianopeck(a)gmail.com> wrote:
>>
>> Hi guys. The linux Cog VM from hudson has broken the finalization. Just run the WeakRegistryTest and you will see the broken test. It might happened because of the ephemerons because Eliot's VM works correctly.
>> Even more, the VM from Jenkis is correct. So....I would remove the broken one from Hudson.
>>
>
> I migrated unix and windows VM jobs to Jenkins.
> Please use VMs built on Jenkins servers.
>
Can we delete the Hudson projects? Just to avoid confusion?
--
Marcus Denker -- http://marcusdenker.de
Aug. 25, 2011
Re: [Pharo-project] [Vm-dev] Cog in Jenkis has brokken finalization
by Igor Stasenko
On 25 August 2011 14:38, Mariano Martinez Peck <marianopeck(a)gmail.com> wrote:
>
> Hi guys. The linux Cog VM from hudson has broken the finalization. Just run the WeakRegistryTest and you will see the broken test. It might happened because of the ephemerons because Eliot's VM works correctly.
> Even more, the VM from Jenkis is correct. So....I would remove the broken one from Hudson.
>
I migrated unix and windows VM jobs to Jenkins.
Please use VMs built on Jenkins servers.
> Cheers
>
> --
> Mariano
> http://marianopeck.wordpress.com
>
>
>
--
Best regards,
Igor Stasenko AKA sig.
Aug. 25, 2011
[Pharo-project] Cog in Jenkis has brokken finalization
by Mariano Martinez Peck
Hi guys. The linux Cog VM from hudson has broken the finalization. Just run
the WeakRegistryTest and you will see the broken test. It might happened
because of the ephemerons because Eliot's VM works correctly.
Even more, the VM from Jenkis is correct. So....I would remove the broken
one from Hudson.
Cheers
--
Mariano
http://marianopeck.wordpress.com
Aug. 25, 2011
[Pharo-project] HelpSystem added to CollaborActive book
by Sean P. DeNigris
A short description by its creator, Torsten. And a link to the PharoCast.
http://book.pharo-project.org/book/PharoTools/HelpSystem
Sean
--
View this message in context: http://forum.world.st/HelpSystem-added-to-CollaborActive-book-tp3768092p376…
Sent from the Pharo Smalltalk mailing list archive at Nabble.com.
Aug. 25, 2011