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).
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
_______________________________________________
Pharo-project mailing list
[email protected]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project