That is good news, that it is due to this code doing funniness than a VM issue. This code trying to bring asynchrony within a synchronous environment brings new issues. What do you think that right solution is to the issue of a call expected to be immediate, change out to go eventual until the arguments resolve? How can it be structured correctly on the stack without generic functions? I think with the double dispatch of an eventual but I have not spend much time in this particular area. Preventing the vm from crashing would be a good interim step but even here I am not sure how to go about crafting a solution. Thank you for investigating this. - HH On Wed, Aug 16, 2017 at 20:46, Eliot Miranda <eliot.miranda@gmail.com> wrote:
Hi Henry, Hi Marcus,
On Sun, Aug 13, 2017 at 5:08 AM, henry <henry@callistohouse.club> wrote:
Hi all. I was testing with this eventual_test package and it blows up the pharo 6.1 vm. I'd welcome pointers
http://www.squeaksource.com/TurquoiseTesting.html
- HH
I took a look at this and I think you've found a bug in the mustBeBooleanMagic: code. What's happening is a mustBeBoolean in Integer>>* due to evaluating 10 * 42 eventual in RefsTest>>testFailureArithmeticPrimitivesWithPromiseArgument
Since 42 eventual is a NearERef the SmallInteger>>* primitive fails and does ^super * anInteger (where anInteger is the NearERef). So that evaluates Integer>>*
Integer>>* aNumber "Refer to the comment in Number * " aNumber isInteger ifTrue: [^ self digitMultiply: aNumber neg: self negative ~~ aNumber negative]. ^ aNumber adaptToInteger: self andSend: #*
aNumber, being a NearERef, answers a PromiseERef for the isInteger send, and this provokes a mustBeBoolean for the isInteger ifTrue: [...
After the mustBeBooleanMagic: the stack looks wrong. The activation of Integer>>*, which is about to do ^ aNumber adaptToInteger: self andSend: #* does not have enough items on the stack. Instead of containing a NearERef (for 42) 10 #* it contains a PromiseERef (for 42 eventual isInteger) and the send of #adaptToInteger:andSend: ends up taking more form the stack than the VM can handle and it crashes. The bug appears to be with the use of sendNode irInstruction nextBytecodeOffsetAfterJump in Object>>mustBeBooleanMagic: since execution should resume at bytecode 55 below, but does so at bytecode 57
41 <10> pushTemp: 0 42 <D0> send: isInteger 43 <AC 09> jumpFalse: 54 45 <70> self 46 <10> pushTemp: 0 47 <70> self 48 <D1> send: negative 49 <10> pushTemp: 0 50 <D1> send: negative 51 <E2> send: ~~ 52 <F3> send: digitMultiply:neg: 53 <7C> returnTop 54 <10> pushTemp: 0 55 <70> self 56 <24> pushConstant: #* 57 <F5> send: adaptToInteger:andSend: 58 <7C> returnTop
So the positioning of the context's pc must be before any argument marshaling for the next send, not simply the send itself.
Put a breakpoint at the end of Object>>mustBeBooleanMagic: and add initlaPC and resumePC temporaries at the beginning and capture them via initialPC := context pc. at the beginning and then context pc: (resumePC := sendNode irInstruction nextBytecodeOffsetAfterJump) to see what I'm seeing.
Phew. Glad it's not a VM bug :-)
HTH _,,,^..^,,,_ best, Eliot