[Pharo-dev] eventual crashes pharo vm
henry at callistohouse.club
Wed Aug 16 23:46:48 EDT 2017
I have disabled that test for the time being. It will require some deeper thought regarding immediate selectors, I think, and I am deep into another area right now. As mustBeBoolean is from inside the VM, a different approach may be the right solution. A part of me thinks autocoercion between msg sending (async) and msg calling (sync) is what is needed, but I want continuation-based VatSemaphores to prevent a liveness lock on the event loop to support. Again, I have not thought deep enough in this area.
Thanks again for your help,
> -------- Original Message --------
> Subject: Re: [Pharo-dev] eventual crashes pharo vm
> Local Time: August 16, 2017 10:32 PM
> UTC Time: August 17, 2017 2:32 AM
> From: eliot.miranda at gmail.com
> To: henry <henry at callistohouse.club>
> Marcus Denker <marcus.denker at inria.fr>, Pharo Development List <pharo-dev at lists.pharo.org>, Squeak Virtual Machine Development Discussion <vm-dev at lists.squeakfoundation.org>
> Hi Henry,
> On Wed, Aug 16, 2017 at 6:33 PM, henry <henry at callistohouse.club> wrote:
>> 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?
> I'm not informed enough to know. One could implement mustBeBoolean in the ERef hierarchy and resolve the promise before going on. One could rely on the mustBeBooleanMagic: if one wanted a fully lazy system. I don't know the trade-offs between the two. I do know that while the miustBeBooleanMagic: solution is cool and fun it is extremely slow. So if performance is an issue use the first approach.
>> 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.
> Yes that's an issue There is already a problem with #==. It needs to be symmetric for correctness.
>> 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.
> Well, the issue is simply that the wrong pc is chosen for the continuation after the mustBeBoolean. I'm sure the right answer is straight-forward to obtain.
>> Thank you for investigating this.
> You're welcome.
>> - HH
>> On Wed, Aug 16, 2017 at 20:46, Eliot Miranda <eliot.miranda at gmail.com> wrote:
>>> Hi Henry, Hi Marcus,
>>> On Sun, Aug 13, 2017 at 5:08 AM, henry <henry at 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
>>>> - 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)
>>> 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 :-)
>>> best, Eliot
> best, Eliot
-------------- next part --------------
An HTML attachment was scrubbed...
More information about the Pharo-dev