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! |
Free forum by Nabble | Edit this page |