[Pkg] The Trunk: Kernel-eem.1141.mcz

commits at source.squeak.org commits at source.squeak.org
Thu Jan 11 17:23:01 UTC 2018


Eliot Miranda uploaded a new version of Kernel to project The Trunk:
http://source.squeak.org/trunk/Kernel-eem.1141.mcz

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

Name: Kernel-eem.1141
Author: eem
Time: 11 January 2018, 9:22:51.439093 am
UUID: a64a9457-407a-40f0-8d51-111106f0afdf
Ancestors: Kernel-eem.1140

Move BlockLocalTempCounter to Kernel.  It is used to implement BlockClosure>>numTemps, which is used more broadly than simply the decompiler and debugger.

=============== Diff against Kernel-eem.1140 ===============

Item was added:
+ InstructionClient subclass: #BlockLocalTempCounter
+ 	instanceVariableNames: 'stackPointer scanner blockEnd joinOffsets'
+ 	classVariableNames: ''
+ 	poolDictionaries: ''
+ 	category: 'Kernel-Methods'!
+ 
+ !BlockLocalTempCounter commentStamp: 'eem 1/11/2018 08:30' prior: 0!
+ I am a support class for the decompiler that is used to find the number of local temps in a block by finding out what the stack offset is at the end of a block.  I am necessary because in the EncoderForV3PlusClosures bytecode set the only way to initialize block-local temporaries is with pushConstant: nil bytecodes, but such bytecodes are ambiguous with a pushConstant: nil used to pass nil as a parameter or answer it as a result.  By scanning through to the end of the block these can be disambiguated by tracking the stack depth.!

Item was added:
+ ----- Method: BlockLocalTempCounter class>>tempCountForBlockAt:in: (in category 'instance creation') -----
+ tempCountForBlockAt: pc in: method
+ 	^self new tempCountForBlockAt: pc in: method!

Item was added:
+ ----- Method: BlockLocalTempCounter class>>tempCountForBlockStartingAt:in: (in category 'instance creation') -----
+ tempCountForBlockStartingAt: startpc in: method
+ 	^self new
+ 		tempCountForBlockAt: (method encoderClass pcOfBlockCreationBytecodeForBlockStartingAt: startpc in: method)
+ 		in: method!

Item was added:
+ ----- Method: BlockLocalTempCounter>>blockReturnConstant: (in category 'instruction decoding') -----
+ blockReturnConstant: value
+ 	"Return Constant From Block bytecode."
+ 	scanner pc < blockEnd ifTrue:
+ 		[self doJoin]!

Item was added:
+ ----- Method: BlockLocalTempCounter>>blockReturnTop (in category 'instruction decoding') -----
+ blockReturnTop
+ 	"Return Top Of Stack bytecode."
+ 	stackPointer := stackPointer - 1.
+ 	scanner pc < blockEnd ifTrue:
+ 		[self doJoin]!

Item was added:
+ ----- Method: BlockLocalTempCounter>>directedSuperSend:numArgs: (in category 'instruction decoding') -----
+ directedSuperSend: selector numArgs: numArgs
+ 	"Send Message Above Specific Class With Selector, selector, bytecode.
+ 	 Start the lookup above the class that is the value of the association on
+ 	 top of stack. The arguments  of the message are found in the top numArgs
+ 	 stack locations beneath the association, and the receiver just below them."
+ 
+ 	stackPointer := stackPointer - (numArgs + 1)!

Item was added:
+ ----- Method: BlockLocalTempCounter>>doDup (in category 'instruction decoding') -----
+ doDup
+ 	"Duplicate Top Of Stack bytecode."
+ 	stackPointer := stackPointer + 1!

Item was added:
+ ----- Method: BlockLocalTempCounter>>doJoin (in category 'private') -----
+ doJoin
+ 	scanner pc < blockEnd ifTrue:
+ 		[stackPointer := joinOffsets at: scanner pc ifAbsent: [scanner followingPc]]
+ 
+ 	"the ifAbsent: handles a caseOf:otherwise: where all cases return, which results
+ 	 in the branch around the otherwise being unreached.  e.g. in the following
+ 		jumpTo: L2
+ 	 is unreached.
+ 
+ 		| t |
+ 		t caseOf: { [nil] -> [^thisContext method abstractSymbolic] }
+ 		  otherwise: ['Oh no Mr Bill!!']
+ 
+ 		pushTemp: 0
+ 		pushConstant: nil
+ 		send: #= (1 arg)
+ 		jumpFalseTo: L1
+ 		pushThisContext: 
+ 		send: #method (0 args)
+ 		send: #abstractSymbolic (0 args)
+ 		returnTop
+ 		jumpTo: L2
+ 	L1:
+ 		pushConstant: 'Oh no Mr Bill!!'
+ 	L2:
+ 		returnTop"!

Item was added:
+ ----- Method: BlockLocalTempCounter>>doPop (in category 'instruction decoding') -----
+ doPop
+ 	"Remove Top Of Stack bytecode."
+ 	stackPointer := stackPointer - 1!

Item was added:
+ ----- Method: BlockLocalTempCounter>>jump: (in category 'instruction decoding') -----
+ jump: offset
+ 	"Unconditional Jump bytecode."
+ 	offset > 0 ifTrue:
+ 		[joinOffsets at: scanner pc + offset put: stackPointer.
+ 		 self doJoin]!

Item was added:
+ ----- Method: BlockLocalTempCounter>>jump:if: (in category 'instruction decoding') -----
+ jump: offset if: condition 
+ 	"Conditional Jump bytecode."
+ 	stackPointer := stackPointer - 1.
+ 	offset > 0 ifTrue:
+ 		[joinOffsets at: scanner pc + offset put: stackPointer]!

Item was added:
+ ----- Method: BlockLocalTempCounter>>methodReturnConstant: (in category 'instruction decoding') -----
+ methodReturnConstant: value 
+ 	"Return Constant bytecode."
+ 	self doJoin!

Item was added:
+ ----- Method: BlockLocalTempCounter>>methodReturnReceiver (in category 'instruction decoding') -----
+ methodReturnReceiver
+ 	"Return Self bytecode."
+ 	self doJoin!

Item was added:
+ ----- Method: BlockLocalTempCounter>>methodReturnTop (in category 'instruction decoding') -----
+ methodReturnTop
+ 	"Return Top Of Stack bytecode."
+ 	stackPointer := stackPointer - 1.
+ 	self doJoin!

Item was added:
+ ----- Method: BlockLocalTempCounter>>popIntoLiteralVariable: (in category 'instruction decoding') -----
+ popIntoLiteralVariable: anAssociation 
+ 	"Remove Top Of Stack And Store Into Literal Variable bytecode."
+ 	stackPointer := stackPointer - 1!

Item was added:
+ ----- Method: BlockLocalTempCounter>>popIntoReceiverVariable: (in category 'instruction decoding') -----
+ popIntoReceiverVariable: offset 
+ 	"Remove Top Of Stack And Store Into Instance Variable bytecode."
+ 	stackPointer := stackPointer - 1!

Item was added:
+ ----- Method: BlockLocalTempCounter>>popIntoRemoteTemp:inVectorAt: (in category 'instruction decoding') -----
+ popIntoRemoteTemp: remoteTempIndex inVectorAt: tempVectorIndex
+ 	"Remove Top Of Stack And Store Into Offset of Temp Vector bytecode."
+ 	stackPointer := stackPointer - 1!

Item was added:
+ ----- Method: BlockLocalTempCounter>>popIntoTemporaryVariable: (in category 'instruction decoding') -----
+ popIntoTemporaryVariable: offset 
+ 	"Remove Top Of Stack And Store Into Temporary Variable bytecode."
+ 	stackPointer := stackPointer - 1!

Item was added:
+ ----- Method: BlockLocalTempCounter>>pushActiveContext (in category 'instruction decoding') -----
+ pushActiveContext
+ 	"Push Active Context On Top Of Its Own Stack bytecode."
+ 	stackPointer := stackPointer + 1!

Item was added:
+ ----- Method: BlockLocalTempCounter>>pushClosureCopyNumCopiedValues:numArgs:blockSize: (in category 'instruction decoding') -----
+ pushClosureCopyNumCopiedValues: numCopied numArgs: numArgs blockSize: blockSize
+ 	"Push Closure bytecode.  Either compute the end of the block if this is
+ 	 the block we're analysing, or skip it, adjusting the stack as appropriate."
+ 	blockEnd
+ 		ifNil: [blockEnd := scanner pc + blockSize]
+ 		ifNotNil:
+ 			[stackPointer := stackPointer - numCopied + 1.
+ 			 scanner pc: scanner pc + blockSize]!

Item was added:
+ ----- Method: BlockLocalTempCounter>>pushConsArrayWithElements: (in category 'instruction decoding') -----
+ pushConsArrayWithElements: numElements
+ 	"Push Cons Array of size numElements popping numElements items from the stack into the array bytecode."
+ 	stackPointer := stackPointer - numElements + 1!

Item was added:
+ ----- Method: BlockLocalTempCounter>>pushConstant: (in category 'instruction decoding') -----
+ pushConstant: value
+ 	"Push Constant, value, on Top Of Stack bytecode."
+ 	stackPointer := stackPointer + 1!

Item was added:
+ ----- Method: BlockLocalTempCounter>>pushFullClosure:numCopied: (in category 'instruction decoding') -----
+ pushFullClosure: aCompiledBlock numCopied: numCopied
+ 	"Push Full Closure bytecode."
+ 	self error: 'BlockLocalTempCounter should not be used with full block compiled methods.  A full block''s numTemps is accessible directly from its method.'!

Item was added:
+ ----- Method: BlockLocalTempCounter>>pushLiteralVariable: (in category 'instruction decoding') -----
+ pushLiteralVariable: anAssociation
+ 	"Push Contents Of anAssociation On Top Of Stack bytecode."
+ 	stackPointer := stackPointer + 1!

Item was added:
+ ----- Method: BlockLocalTempCounter>>pushNewArrayOfSize: (in category 'instruction decoding') -----
+ pushNewArrayOfSize: numElements 
+ 	"Push New Array of size numElements bytecode."
+ 	stackPointer := stackPointer + 1!

Item was added:
+ ----- Method: BlockLocalTempCounter>>pushReceiver (in category 'instruction decoding') -----
+ pushReceiver
+ 	"Push Active Context's Receiver on Top Of Stack bytecode."
+ 	stackPointer := stackPointer + 1!

Item was added:
+ ----- Method: BlockLocalTempCounter>>pushReceiverVariable: (in category 'instruction decoding') -----
+ pushReceiverVariable: offset
+ 	"Push Contents Of the Receiver's Instance Variable Whose Index 
+ 	is the argument, offset, On Top Of Stack bytecode."
+ 	stackPointer := stackPointer + 1!

Item was added:
+ ----- Method: BlockLocalTempCounter>>pushRemoteTemp:inVectorAt: (in category 'instruction decoding') -----
+ pushRemoteTemp: remoteTempIndex inVectorAt: tempVectorIndex
+ 	"Push Contents at Offset in Temp Vector bytecode."
+ 	stackPointer := stackPointer + 1!

Item was added:
+ ----- Method: BlockLocalTempCounter>>pushTemporaryVariable: (in category 'instruction decoding') -----
+ pushTemporaryVariable: offset
+ 	"Push Contents Of Temporary Variable Whose Index Is the 
+ 	argument, offset, On Top Of Stack bytecode."
+ 	stackPointer := stackPointer + 1!

Item was added:
+ ----- Method: BlockLocalTempCounter>>send:super:numArgs: (in category 'instruction decoding') -----
+ send: selector super: supered numArgs: numberArguments
+ 	"Send Message With Selector, selector, bytecode. The argument, 
+ 	supered, indicates whether the receiver of the message is specified with 
+ 	'super' in the source method. The arguments of the message are found in 
+ 	the top numArguments locations on the stack and the receiver just 
+ 	below them."
+ 
+ 	stackPointer := stackPointer - numberArguments!

Item was added:
+ ----- Method: BlockLocalTempCounter>>tempCountForBlockAt:in: (in category 'initialize-release') -----
+ tempCountForBlockAt: pc in: method
+ 	"Compute the number of local temporaries in a block.
+ 	 If the block begins with a sequence of push: nil bytecodes then some of
+ 	 These could be initializing local temps.  We can only reliably disambuguate
+ 	 them from other uses of nil by parsing the stack and seeing what the offset
+ 	 of the stack pointer is at the end of the block.
+ 
+ 	 There are short-cuts.  The ones we take here are
+ 		- if there is no sequence of push nils there can be no local temps
+ 		- we follow forward jumps to shorten the amount of scanning"
+ 	stackPointer := 0.
+ 	scanner := InstructionStream new method: method pc: pc.
+ 	scanner interpretNextInstructionFor: self.
+ 	blockEnd ifNil:
+ 		[self error: 'pc is not that of a block'].
+ 	scanner nextByte = method encoderClass pushNilCode ifTrue:
+ 		[joinOffsets := Dictionary new.
+ 		 [scanner pc < blockEnd] whileTrue:
+ 			[scanner interpretNextInstructionFor: self]].
+ 	^stackPointer!

Item was added:
+ ----- Method: BlockLocalTempCounter>>testTempCountForBlockAt:in: (in category 'initialize-release') -----
+ testTempCountForBlockAt: startPc in: method
+ 	"Compute the number of local temporaries in a block.
+ 	 If the block begins with a sequence of push: nil bytecodes then some of
+ 	 These could be initializing local temps.  We can only reliably disambuguate
+ 	 them from other uses of nil by parsing the stack and seeing what the offset
+ 	 of the stack pointer is at the end of the block.There are short-cuts.  The only
+ 	 one we take here is
+ 		- if there is no sequence of push nils there can be no local temps"
+ 
+ 	| symbolicLines line prior thePc |
+ 	symbolicLines := Dictionary new.
+ 	method symbolicLinesDo:
+ 		[:pc :lineForPC| symbolicLines at: pc put: lineForPC].
+ 	stackPointer := 0.
+ 	scanner := InstructionStream new method: method pc: startPc.
+ 	scanner interpretNextInstructionFor: self.
+ 	blockEnd ifNil:
+ 		[self error: 'pc is not that of a block'].
+ 	scanner nextByte = method encoderClass pushNilCode ifTrue:
+ 		[joinOffsets := Dictionary new.
+ 		 [scanner pc < blockEnd] whileTrue:
+ 			[line := symbolicLines at: scanner pc.
+ 			 prior := stackPointer.
+ 			 thePc := scanner pc.
+ 			 scanner interpretNextInstructionFor: self.
+ 			 Transcript cr; print: prior; nextPutAll: '->'; print: stackPointer;  tab; print: thePc; tab; nextPutAll: line; flush]].
+ 	^stackPointer!



More information about the Packages mailing list