[squeak-dev] Re: Bug with valueWithReceiver:arguments:
Eliot Miranda
eliot.miranda at gmail.com
Mon Oct 27 02:13:10 UTC 2008
On Sun, Oct 26, 2008 at 6:21 AM, Klaus D. Witzel <klaus.witzel at cobss.com>wrote:
> On Sun, 26 Oct 2008 13:39:04 +0100, Andreas Raab wrote:
>
> Hi Frederic -
>>
>> Congrats! You found the first real VM bug in five years or so ;-) I'm not
>> completely sure what the problem is but there is obviously something wrong
>> here. It's easiest to recreate the problem by copying the #/ method and
>> simply do something like:
>>
>> SmallInteger>>foo: aNumber
>> "(SmallInteger>>#foo:) valueWithReceiver: 11 arguments: {2}"
>> <primitive: 10>
>> self halt.
>> aNumber isZero ifTrue: [^(ZeroDivide dividend: self) signal].
>> (aNumber isMemberOf: SmallInteger)
>> ifTrue: [^(Fraction numerator: self denominator: aNumber)
>> reduced]
>> ifFalse: [^super / aNumber]
>>
>> When you run this, you'll see that the debugger shows *two* frames with
>> SmallInteger>>foo: on them. Inspecting the "parent" frame will eventually
>> crash the system since it has a completely bogus stack pointer (-1).
>>
>> It seems that in a failing primitive method we end up with a bogus
>> activation record in primitiveExecMethodWithArgs (removing the primitive
>> from the above makes it work fine). I'm somewhat at a loss here as to what
>> the problem might be given that the implementations of primPerformWithArgs
>> and primExecWithArgs are so similar but interestingly, the equivalent:
>>
>> 11 perform: #foo: withArguments:{2}.
>>
>> works fine with or without the primitive. Somewhere there must be a
>> difference ...
>>
>
> The difference can be this: #primitiveExecuteMethod is called as part of
> #primitiveResponse, and in turn calls #executeNewMethod which again does
> #primitiveResponse. If the latter does #primitiveFail, the now *two*
> activations of #primitiveResponse want to handle the situation - without
> knowing from each other.
>
> Perhaps #primitiveExecuteMethod should end with an explicit [ ... ^ self
> success: true] in its true-branch (this is just a thought, I have as yet not
> looked deeper).
I think you're exactly right. This fixes it for me.
Thanks!
> Besides: if #primitiveExecuteMethod would do its own #primitiveFail, it
> looks like its arguments are no longer on the stack.
>
> /Klaus
>
>
> Cheers,
>> - Andreas
>>
>> Frederic Pluquet wrote:
>>
>>> Hello,
>>> I found a fondamental bug in Squeak and Pharo. The next code
>>> 11 / 2 gives the fraction (11/2). It's correct. But the next code
>>> (SmallInteger>>#/) valueWithReceiver: 11 arguments: {2}
>>> gives 1 !
>>> The problem is the method valueWithReceiver:arguements: is used hugely
>>> with method wrappers...
>>> After long time of debugging, I found a point to debug: this method
>>> don't have the good behavior with compiled methods having a primitive that
>>> fails and executes some code after (as in SmallInteger>>#/ method when the
>>> division don't give a whole integer). In fact, when I send this message, the
>>> vm executes normally the compiled method but, in place of returns simply the
>>> good result, seems to rerun the the compiled method with other arguments
>>> (completly wrong) and returns so a wrong result.
>>> For example, (SmallInteger>>#/) valueWithReceiver: 11 arguments: {2}
>>> has the following execution trace :
>>> 2 isZero
>>> | 2 = 0
>>> | returns: false
>>> returns: false
>>> 2 isMemberOf: SmallInteger
>>> | 2 class
>>> | returns: SmallInteger
>>> | SmallInteger == SmallInteger
>>> | returns: true
>>> returns: true
>>> Fraction numerator: 101 denominator: 2
>>> | Fraction new
>>> | | Fraction basicNew
>>> | | returns: a Fraction instance
>>> | | (a Fraction instance) initialize
>>> | | returns: a Fraction instance
>>> | returns: a Fraction instance
>>> | a Fraction instance setNumerator: 101 denominator: 2
>>> | | 2 = 0
>>> | | returns: false
>>> | | 101 asInteger
>>> | | returns: 101
>>> | | 2 asInteger
>>> | | returns: 2
>>> | | 2 abs
>>> | | | 2 < 0
>>> | | | returns: false
>>> | | returns: 2
>>> | | 2 < 0
>>> | | returns: false
>>> | returns: (101/2)
>>> returns: (101/2)
>>> (101/2) reduced
>>> | 101 = 0
>>> | returns: false
>>> | 101 gcd: 2
>>> | | 101 = 0
>>> | | returns: false
>>> | | 2 \\ 101
>>> | | returns: 2
>>> | | 2 = 0
>>> | | returns: false
>>> | | 101 \\ 2
>>> | | returns: 1
>>> | | 1 = 0
>>> | | returns: false
>>> | | 2 \\ 1
>>> | | returns: 0
>>> | | 0 = 0
>>> | | returns: true
>>> | | 1 abs
>>> | | | 1 < 0
>>> | | | returns: false
>>> | | returns: 1
>>> | returns: 1
>>> | 101 // 1
>>> | returns: 101
>>> | 2 // 1
>>> | returns: 2
>>> | 2 = 1
>>> | returns: false
>>> | Fraction numerator: 101 denominator: 2
>>> | | Fraction new
>>> | | | Fraction basicNew
>>> | | | returns: a Fraction instance
>>> | | | (a Fraction instance) initialize
>>> | | | returns: a Fraction instance
>>> | | returns: a Fraction instance
>>> | | (a Fraction instance) setNumerator: 101 denominator: 2
>>> | | | 2 = 0
>>> | | | returns: false
>>> | | | 101 asInteger
>>> | | | returns: 101
>>> | | | 2 asInteger
>>> | | | returns: 2
>>> | | | 2 abs
>>> | | | | 2 < 0
>>> | | | | returns: false
>>> | | | returns: 2
>>> | | | 2 < 0
>>> | | | returns: false
>>> | | returns: (101/2)
>>> | returns: (101/2)
>>> returns: (101/2)
>>> 2 isZero
>>> | 2 = 0
>>> | returns: false
>>> returns: false
>>> false isMemberOf: SmallInteger
>>> | false class
>>> | returns: False
>>> | False == SmallInteger
>>> | returns: false
>>> returns: false
>>> Please help me to fix this bug. I really need it works fine !
>>> Fréd
>>> -- Frédéric Pluquet
>>> Université Libre de Bruxelles (ULB)
>>> Assistant
>>> http://www.ulb.ac.be/di/fpluquet
>>> ------------------------------------------------------------------------
>>>
>>>
>>
>>
>>
>
>
> --
> "If at first, the idea is not absurd, then there is no hope for it". Albert
> Einstein
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20081026/0017e1ca/attachment.htm
More information about the Squeak-dev
mailing list
|