VM or COM bug?

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

VM or COM bug?

ar-2
Andy and Blair,

I'm encountering some very strange problems which I think might be VM or COM
related. The code in question is as follows:

Bar method:

onChangedFields: aTwoArgBlock

        self fooNames do: [ : fnam |
                self = nil ifTrue:[self halt]. "should never hit this.."
                (self fooAt: fnam)  onChangedFields: [ : fields | "line 5"
                        aTwoArgBlock value: fnam value: fields ]  ] "line 6"

fooNames is an anOrderedCollection with 'a' 'b' 'c'.

If I just run into this code i hit the halt every time at the top of the 2nd
iteration. Debugging it,

I single-step until line 5 & 6 are highlighted.

At this point the following shows in the variables pane in the debugger:

self = the receiver
aTwoArgBlock = the block passed in
fnam = 'a'

This is all normal.

Then I press "step over". now:

self = nil.

*sometimes*:
aTwoArgBlock = the fooNames collection (an instVar in the receiver)
fnam = an instance variable in the receiver ].

I have absolutely definitely seen these 3 values change their contents just by
clicking on them in various orders in the debugger. For example with the
debugger at the halt just now I clicked on self, it was nil, then clicked on
aTwoArgBlock and fnam and they were bad, then clicked back on self and it was
back to being the receiver.

The problem does depend on the code in line 5 & 6.
If i comment "onChangedFields:[ : fields |... ]" the problem goes away.
Likewise if I change the implementation of Foo>>#onChangedFields: to a no-op.

Foo>>#onChangedFields: looks like this:

onChangedFields: aBlock

        self controlSite when: #ChangedFields: perform: aBlock

where controlSite is an AXControlSite.

I tried stepping into the #when:perform and as best I can tell, the damage
doesnt occur until the stack is unwinding back to the top method.

So far, I dont know how to isolate this into a test case.  I'm hoping that
just the above might yield a clue. My guess is that if there weren't any
ActiveX objects involved this problem is NR. It's probably going to be a bear
to make a clean test case. But I'll do whatever it takes to help repro it.

(This code has another bug which is unrelated  to the self problem. The inner
blocks are bound to the "wrong" value of "fnam". [perhaps this is a
"feature"?]. On Dolphin,  

(#(1 2) collect: [ :each | [each]]) first value

evaluates to 2, whereas on VisualSmalltalk the answer is 1, which is what I
expect. Im not sure which one is "standard". But I think I am strongly going
to miss the VSE behavior)


Reply | Threaded
Open this post in threaded view
|

Re: VM or COM bug?

Stefan Schmiedl
On Thu, 10 Jan 2002 01:22:15 GMT, ar <[hidden email]> wrote:

> On Dolphin,  
>
> (#(1 2) collect: [ :each | [each]]) first value
>
> evaluates to 2, whereas on VisualSmalltalk the answer is 1, which is what I
> expect. Im not sure which one is "standard". But I think I am strongly going
> to miss the VSE behavior)

Squeak does this, too ... so it's two to one it's a bug in VS :-)

What does

   (#(1 2) collect: [ :each | [each]]) last value

give in VSE?

I'd say that Dolphin and Squeak are storing references to "an
iteration variable" in the block, and after finishing the collect:
the binding points to the last element in the sequence.


s.


Reply | Threaded
Open this post in threaded view
|

Re: VM or COM bug?

Eliot Miranda
Stefan Schmiedl wrote:

>
> On Thu, 10 Jan 2002 01:22:15 GMT, ar <[hidden email]> wrote:
>
> > On Dolphin,
> >
> > (#(1 2) collect: [ :each | [each]]) first value
> >
> > evaluates to 2, whereas on VisualSmalltalk the answer is 1, which is what I
> > expect. Im not sure which one is "standard". But I think I am strongly going
> > to miss the VSE behavior)

VSE is right, and is exhibiting standard (i.e. ANSI-standard) behaviour.

>
> Squeak does this, too ... so it's two to one it's a bug in VS :-)

You'll find most commercial Smalltalks agree with VS, VisualWorks,
VisualAge and Smalltalk Agents included.

>
> What does
>
>    (#(1 2) collect: [ :each | [each]]) last value
>
> give in VSE?
>
> I'd say that Dolphin and Squeak are storing references to "an
> iteration variable" in the block, and after finishing the collect:
> the binding points to the last element in the sequence.
>
> s.

This is an old bug in the specification/implementation of Smalltalk-80,
as given in the blue book.  In Smalltalk-76 through Smalltalk-80 block
argument variables are actually allocated on the stack frame of the
enclosing method context.  i.e. in the above there is only one physical
memory location being used to represent each.  In fact the code could be
written

    | each |
    #(1 2) collect: [ :each | [each]].
    each

and it would print 2.  This is definitely a bug in Squeak and Dolphin,
but an understandable and long standing one.  ANSI Smalltalk requires
that each each above have a distinct memory location.  Of course making
this change is, um, non-trivial and potentially has far reaching
effects.  Andy and Blair are well aware of the issue.  Until they fix
it, "don't do that" :)
--
_______________,,,^..^,,,____________________________
Eliot Miranda              Smalltalk - Scene not herd


Reply | Threaded
Open this post in threaded view
|

Re: VM or COM bug?

ar-2
On Thu, 10 Jan 2002 23:23:04 GMT, Eliot Miranda <[hidden email]> wrote:

>You'll find most commercial Smalltalks agree with VS, VisualWorks,
>VisualAge and Smalltalk Agents included.
>
>This is an old bug in the specification/implementation of Smalltalk-80,
>as given in the blue book.  In Smalltalk-76 through Smalltalk-80 block
>argument variables are actually allocated on the stack frame of the
>enclosing method context.  i.e. in the above there is only one physical
>memory location being used to represent each.  In fact the code could be
>written
>
>    | each |
>    #(1 2) collect: [ :each | [each]].
>    each
>
>and it would print 2.  This is definitely a bug in Squeak and Dolphin,
>but an understandable and long standing one.  ANSI Smalltalk requires
>that each each above have a distinct memory location.  Of course making
>this change is, um, non-trivial and potentially has far reaching
>effects.  Andy and Blair are well aware of the issue.  Until they fix
>it, "don't do that" :)

Eliot,

Coming from VS, it is going to take some "deprogramming" for me to learn to
live without it. When I tried to rewrite my original code, I realized it's not
so simple to "dont do that". The ANSI behavior is significant. I concluded
that the only way in general to translate code which depended on the ANSI
behavior is to introduce another method context into the mix. In my example:

onChangedFields: aTwoArgBlock

        self fooNames do: [ : fnam|
                (self fooAt: fnam) onChangedFields: [ : fields |
                        aTwoArgBlock value: fnam value: fields ]  ]

becomes:

onChangedFields: aTwoArgBlock

        self fooNames do: [ : fnam |
                self onChangedFields: aTwoArgBlock in: fnam ]

onChangedFields: aTwoArgBlock in: fnam

        (self fooAt: fnam) onChangedFields: [ : fields |
                aTwoArgBlock value: fnam value: fields]

which is not expressed as well.

There appears to be no "trick" for getting each inner block instance to have a
distinct value in the single-method version. I'd love to be proven wrong
though..


Reply | Threaded
Open this post in threaded view
|

Re: VM or COM bug?

Eliot Miranda
ar wrote:
[snip]

> There appears to be no "trick" for getting each inner block instance to have a
> distinct value in the single-method version. I'd love to be proven wrong
> though..

I think you're right; one needs to rewrite the code.  There are
various rewrites one can imagine that might be less intrusive than
yours and might be applicable automatically.  But these either
break the VM or amount to fixing the problem.
--
_______________,,,^..^,,,____________________________
Eliot Miranda              Smalltalk - Scene not herd