The Trunk: Kernel-eem.1141.mcz

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

The Trunk: Kernel-eem.1141.mcz

commits-2
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!