[Cuis-dev] Changes to unwind logic and termination

Jaromir Matas mail at jaromir.net
Thu Nov 20 00:33:59 PST 2025


Hi Juan,

I've patched the previous test to avoid the VM crash. Indeed the problem
was it forced the VM resume "inside" a quick return. Unlike Squeak, you
allowed the Debugger to step into quick returns. What still confuses me
is when you debug  

`true not`

then step into #not and explore thisContext: what's the meaning of the
pc counter relative to the method? It doesn't point to an existing
bytecode (there's none actually) - is it ok? Why 25? It's confusing...

Anyway, the test now passes. If you remove the line:

`ctx tempAt: 2 put: #unwindComplete`

from #unwindAndResume:evaluating:, the test will fail because of the
suspension point on the backward branch of the #whileFalse loop,
demonstrating the reason for adding the additional #ensure:
completionStatus variable value.

Best regards,
Jaromir

On Nov 19 2025, at 8:19 pm, Jaromir Matas via Cuis-dev
<cuis-dev at lists.cuis.st> wrote:

> Hi Juan,
>  
> I wanted to add an interesting test by Christoph testing that
> termination works correctly at each step of the computation. This was
> the test that discovered some treacherous suspension points in the
> unwind mechanism and the motivation for adding the third value to the
> #ensure: complete temp var.
>  
> However, while it works flawlessly in Squeak, it crashes the VM in Cuis
> immediately. Both for the new VM you've just uploaded as well as for the
> previous one. And also regardless whether the latest unwind update
> you've just integrated is applied.
>  
> Please see for yourself: Using the latest image (new VM, updated unwind)
> the crash happens at step 526. I'm enclosing the test with a halt at
> this step for you to explore the process suspendeContext: you see the
> problem happens when terminating inside `true not` evaluation which is a
> quick return. I'm not familiar with how quick return is supposed to work
> precisely here but it looks suspicious to me the Debugger shows pc = 25
> but the method code has no such instruction. In Squeak this doesn't seem
> to be a problem but I'm still not sure where exactly the problem is.
> Maybe, but I'm speculating here wildly, it has something to do with the
> fact that the quick return may not be a VM resumption point and in real
> time (not simulation) the computation would never be stopped (preempted)
> at this particular point, i.e. "inside a quick return", and hence the VM
> crashes when forced to resume in such an undefined point.
>  
> Question: does the quick return evaluate in a separate frame (context)
> or is it inlined or executed similarly like a primitive?
>  
> In an older image the problem happens at a different step but always
> when inside True>>#not.   
>  
> I'm hoping you might spot a problem right away being familiar with quick
> returns :)
>  
> Best,
> Jaromir
>  
> On Nov 19 2025, at 1:18 pm, Juan Vuletich via Cuis-dev
> <cuis-dev at lists.cuis.st> wrote:
>  
>> Hi Jaromir,
>>   
>> On 2025-11-19 6:15 AM, Jaromir Matas via Cuis-dev wrote:
>>   
>>> Hi Juan,
>>>   
>>> On Nov 18 2025, at 10:33 pm, Juan Vuletich via Cuis-dev
>>> <cuis-dev at lists.cuis.st> wrote:
>>>   
>>>   
>>>   
>>>> Hi Jaromir,
>>>>   
>>>> Apologies for the delayed answer. We were midst the FAST Smalltalks
>>>>    
>>>> conference in Argentina and a wonderful course on VM internals by
>>>> Eliot    
>>>>   
>>> What a treat! I just regret Buenos Aires is so far away from Prague :)
>>>   
>> Well, we need to find out how to make it possible for you to join us
>> next year! You'd have a great time. I promise. BTW do you usually
>> attend ESUG conference? Maybe we can meet there next year too.
>>   
>>   
>>   
>>   
>>> I know Eliot had a presentation at Smalltalks 2025; any chance the
>>> presentation was recorded?
>> Yes. There were several other really good presentations, and all of
>> them were recorded. They will be published on YouTube, like those of
>> rpevious years.
>>   
>>   
>>   
>>   
>>>   
>>>   
>>>> and I didn't have any brains left for anything else for a while.
>>>>   
>>>> I just reviewed your changes. These are welcome and important enhancements.
>>>>   
>>>> Thank you for keeping us updated and sinc'ed with Squeak! This is
>>>> most    
>>>> valuable!
>>>>   
>>>>   
>>> All pleasure's mine; Cuis is an invaluable source of feedback and
>>> inspiration. Thank you!
>>>   
>>>   
>>>   
>>>> When I loaded your changes, I found that in #unwindTo:safely: the
>>>> old    
>>>> version had a guard against (ctx tempAt: 1) being nil. Your new code
>>>>    
>>>> doesn't include that guard, and #testTerminateWithNiledUnwindBlock
>>>> will    
>>>> fail. You can also see this with your 'Workspace example' included
>>>> at    
>>>> that test:
>>>>   
>>>>     Workspace example:
>>>>     p := [[Processor activeProcess suspend] ensure: nil] newProcess.
>>>>     p resume.
>>>>     [p terminate] fork
>>>>   
>>>> I found that adding a simple #ifNotNil: appears to solve the issue.
>>>>    
>>>>   
>>> I originally added the nil check and the test but we have discussed this
>>> issue with Christoph Thiede recently and decided to remove the check.
>>> There's no point to guard against nil in place of an unwind block as
>>> it's apparently just a user error and should show up. Only a block
>>> should be allowed as an unwind block. Potentially, the nil check could
>>> even obscure a user's error and make debugging harder (perhaps). This
>>> way the user should be able more quickly identify the error in the Debugger.
>>>   
>>> On the other hand we have a slight inconsistency here: if you run
>>>   
>>>    [] ensure: nil
>>>   
>>> nothing happens, because we have `Object >> #value` returning self :)
>>>    
>>>   
>>> So frankly, I don't have a strong opinion here. A guard is ok too or you
>>> could even use the nil check to raise an explicit error if you
>>> prefer.    
>>>   
>>> In such case one should probably add the same guard to
>>> #unwindAndResume:evaluating: too.
>> I think the analysis you did with Christoph makes total sense. It is
>> better this way. So, I just pushed your code.
>>   
>>   
>>> I'm surprised I forgot to add the test to Squeak :) So depending on your
>>> decision it might want to be moved to expected failures.
>> I just removed that test, and replaced it with a possibly redundant
>> #testTerminateWithEmptyUnwindBlock, just to document all this a bit.
>>   
>>   
>>>   
>>> Thanks again and best regards,
>>> Jaromir
>>>   
>> Thank you. Cheers!
>>   
>> --   
>> Juan Vuletich
>> www.cuis.st
>> github.com/jvuletich
>> researchgate.net/profile/Juan-Vuletich
>> independent.academia.edu/JuanVuletich
>> patents.justia.com/inventor/juan-manuel-vuletich
>> --
>>   
>> Cuis-dev mailing list
>>   
>> Cuis-dev at lists.cuis.st
>>   
>> https://lists.cuis.st/mailman/listinfo/cuis-dev--  
> Cuis-dev mailing list
> Cuis-dev at lists.cuis.st
> https://lists.cuis.st/mailman/listinfo/cuis-dev
> 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: ProcessTest-testTerminateEverywhere_fix.st
Type: application/octet-stream
Size: 866 bytes
Desc: not available
URL: <http://lists.cuis.st/mailman/archives/cuis-dev/attachments/20251120/ce034508/attachment-0001.obj>


More information about the Cuis-dev mailing list