Context inaccurate in debugger

Bob Arning arning at charm.net
Wed Apr 26 16:19:08 UTC 2000


This has puzzled me for a long time and now I see what was wrong.

Cheers,
Bob

===== code follows =====
'From Squeak2.8alpha of 13 January 2000 [latest update: #2040] on 26 April 2000 at 12:09:57 pm'!
"Change Set:		UnusedTempFix
Date:			26 April 2000
Author:			Bob Arning

This corrects (hopefully without breaking anything else) a problem with the Parser: sometimes you look at a method in the debugger and the contents of method temporary variables (lower right pane) are wrong. Values that should clearly be in the slot n are showing up further down the list. 
How it happens:

1. A method is compiled and bytecodes generated.
2. The parser detects unused method temps and removes them after getting confirmation.
3. Sometime later a debugger encounters this method and tries to show the context variables. The problem is that the code was compiled before the removal of the temps from the source, but the debugger is using the current source to figure out where each variable is in the context and may well get it wrong.

The fix is to recompile the method after the unused varaibale have been deleted from the source, thus ensuring consistency"!

Notification subclass: #ParserRemovedUnusedTemps
	instanceVariableNames: ''
	classVariableNames: ''
	poolDictionaries: ''
	category: 'System-Exceptions Tests'!

!Parser methodsFor: 'public access' stamp: 'RAA 4/26/2000 11:59'!
parse: sourceStream class: class noPattern: noPattern context: ctxt notifying: req ifFail: aBlock 
	"Answer a MethodNode for the argument, sourceStream, that is the root of 
	a parse tree. Parsing is done with respect to the argument, class, to find 
	instance, class, and pool variables; and with respect to the argument, 
	ctxt, to find temporary variables. Errors in parsing are reported to the 
	argument, req, if not nil; otherwise aBlock is evaluated. The argument 
	noPattern is a Boolean that is true if the the sourceStream does not 
	contain a method header (i.e., for DoIts)."

	 | meth repeatNeeded startPos myStream |

	myStream _ sourceStream.
	[
		repeatNeeded _ false.
		self init: myStream notifying: req failBlock: [^aBlock value].
		doitFlag _ noPattern.
		encoder _ Encoder new init: class context: ctxt notifying: self.
		failBlock_ aBlock.
		[
			meth _ self method: noPattern context: ctxt.
		] 
			on: ParserRemovedUnusedTemps 
			do: [
				repeatNeeded _ true.
				myStream _ ReadStream on: requestor text string
			].
		repeatNeeded
	] whileTrue.
	encoder _ failBlock _ requestor _ parseNode _ nil. "break cycles & mitigate refct overflow"
	^meth! !

!Parser methodsFor: 'error correction' stamp: 'RAA 4/26/2000 11:05'!
removeUnusedTemps 
	| str end start madeChanges | 

	madeChanges _ false.
	str _ requestor text string.
	((tempsMark between: 1 and: str size)
		and: [(str at: tempsMark) = $|]) ifFalse: [^ self].
	encoder unusedTempNames do:
		[:temp |
		((PopUpMenu labels: 'yes\no' withCRs) startUpWithCaption:
			((temp , ' appears to be
unused in this method.
OK to remove it?') asText makeBoldFrom: 1 to: temp size))
			= 1
		ifTrue:
		[(encoder encodeVariable: temp) isUndefTemp
			ifTrue:
			[end _ tempsMark.
			["Beginning at right temp marker..."
			start _ end - temp size + 1.
			end < temp size or: [temp = (str copyFrom: start to: end)
					and: [(str at: start-1) isSeparator & (str at: end+1) isSeparator]]]
			whileFalse:
				["Search left for the unused temp"
				end _ requestor nextTokenFrom: end direction: -1].
			end < temp size ifFalse:
				[(str at: start-1) = $  ifTrue: [start _ start-1].
				requestor correctFrom: start to: end with: ''.
				str _ str copyReplaceFrom: start to: end with: ''. 
				madeChanges _ true.
				tempsMark _ tempsMark - (end-start+1)]]
			ifFalse:
			[PopUpMenu notify:
'You''ll first have to remove the
statement where it''s stored into']]].
	madeChanges ifTrue: [ParserRemovedUnusedTemps signal].! !





More information about the Squeak-dev mailing list