Posted by
Andreas.Raab on
Oct 26, 2008; 12:39pm
URL: https://forum.world.st/squeak-dev-Bug-with-valueWithReceiver-arguments-tp78494p78495.html
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 ...
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>
>
> ------------------------------------------------------------------------
>
>