[squeak-dev] The Inbox: Kernel-jar.1480.mcz

commits at source.squeak.org commits at source.squeak.org
Thu Jun 9 17:53:36 UTC 2022

A new version of Kernel was added to project The Inbox:

==================== Summary ====================

Name: Kernel-jar.1480
Author: jar
Time: 9 June 2022, 7:53:32.496688 pm
UUID: 1504c554-482d-a94e-b292-ab2c46c6d865
Ancestors: Kernel-mt.1479

Fix a bug: when debugging things like this:

	[^2] ensure: [Transcript cr; show: 'done']

if we step into the protected block [^2] and then step over ^2, we incorrectly get a BlockCannotReturn error. 

Improved comment; please remove Kernel-jar.1415 from the Inbox.

This is an alternative to my older version in Kernel-jar.1421; the solution remains the same but it attempts to present a cleaner code (addressing Christoph's objection in [2] and [3]) and improves the comment.

The bug is described in detail in Kernel-nice.1407 and discussed in [1] and most recently in [2] and [3]:
[1] http://forum.world.st/stepping-over-non-local-return-in-a-protected-block-td5128777.html
[2] http://lists.squeakfoundation.org/pipermail/squeak-dev/2021-August/216214.html
[3] http://lists.squeakfoundation.org/pipermail/squeak-dev/2021-November/216971.html

=============== Diff against Kernel-mt.1479 ===============

Item was changed:
  ----- Method: Context>>resume:through: (in category 'controlling') -----
  resume: value through: firstUnwindCtxt
  	"Unwind thisContext to self and resume with value as result of last send.
  	 Execute any unwind blocks while unwinding.
  	 ASSUMES self is a sender of thisContext."
  	| ctxt unwindBlock |
  	self isDead ifTrue: [self cannotReturn: value to: self].
+ 	ctxt := firstUnwindCtxt value.	"evaluate in case firstUnwindCtxt is a block (see comment in #return:from:)"
- 	ctxt := firstUnwindCtxt.
  	[ctxt isNil] whileFalse:
  		[(ctxt tempAt: 2) ifNil:
  			[ctxt tempAt: 2 put: true.
  			 unwindBlock := ctxt tempAt: 1.
  			 thisContext terminateTo: ctxt.
  			 unwindBlock value].
  		 ctxt := ctxt findNextUnwindContextUpTo: self].
  	thisContext terminateTo: self.

Item was changed:
  ----- Method: Context>>return:from: (in category 'instruction decoding') -----
  return: value from: aSender 
  	"For simulation.  Roll back self to aSender and return value from it.  Execute any unwind blocks on the way.  ASSUMES aSender is a sender of self"
+ 	"Note: when debugging things like this:
+ 		[^2] ensure: [Transcript cr; show: 'done'] 
+ 	if we step into the protected block [^2] and then step over ^2, we incorrectly get a BlockCannotReturn.
+ 	The root cause of this is that during simulation #runUntilErrorOrReturnFrom: inserts a new unwind 
+ 	context between the top of the stack and 'newTop' so we can't supply the next unwind context to 
+ 	#aboutToReturn:through: now but must postpone the search for the next unwind context until the 
+ 	right moment, i.e. until #resume:through: gets executed using the supplied next unwind context.
+ 	One solution is to send a block
+ 		[thisContext findNextUnwindContextUpTo: newTop]
+ 	that will execute the search in #resume:through: instead of sending the next unwind context. 
+ 	Indeed we must modify #resume:through: to evaluate its second argument in case it's this block.
+ 	The objection against such a solution is we are creating a dependency between these two methods.
+ 	See more in http://lists.squeakfoundation.org/pipermail/squeak-dev/2021-August/216214.html"
  	| newTop |
  	aSender isDead ifTrue:
  		[^self send: #cannotReturn: to: self with: {value}].
  	newTop := aSender sender.
  	(self findNextUnwindContextUpTo: newTop) ifNotNil:
+ 		[^self send: #aboutToReturn:through: to: self with: {value. [thisContext findNextUnwindContextUpTo: newTop]}].
- 		[:unwindProtectCtxt|
- 		 ^self send: #aboutToReturn:through: to: self with: {value. unwindProtectCtxt}].
  	self releaseTo: newTop.
  	newTop ifNotNil: [newTop push: value].

More information about the Squeak-dev mailing list