'From Cuis 1.0 of 28 November 2009 [latest update: #337] on 8 December 2009 at 4:48:35 pm'!

!CompiledMethod methodsFor: 'comparing' stamp: 'eem 7/29/2008 14:46'!
= method
	| numLits |
	"Answer whether the receiver implements the same code as the 
	argument, method."
	(method isKindOf: CompiledMethod) ifFalse: [^false].
	self size = method size ifFalse: [^false].
	self header = method header ifFalse: [^false].
	self initialPC to: self endPC do:
		[:i | (self at: i) = (method at: i) ifFalse: [^false]].
	(numLits := self numLiterals) ~= method numLiterals ifTrue: [^false].
	"``Dont bother checking FFI and named primitives''
	 (#(117 120) includes: self primitive) ifTrue: [^ true]."
	1 to: numLits do:
		[:i| | lit1 lit2 |
		lit1 := self literalAt: i.
		lit2 := method literalAt: i.
		lit1 = lit2 ifFalse:
			[(i = 1 and: [#(117 120) includes: self primitive])
				ifTrue: [lit1 isArray
							ifTrue:
								[(lit2 isArray and: [lit1 allButLast = lit2 allButLast]) ifFalse:
									[^false]]
							ifFalse: "ExternalLibraryFunction"
								[(lit1 analogousCodeTo: lit2) ifFalse:
									[^false]]] ifFalse:
			[i = (numLits - 1) ifTrue: "properties"
				[(lit1 analogousCodeTo: lit2) ifFalse:
					[^false]] ifFalse:
			 [lit1 isFloat
				ifTrue:
					["Floats match if values are close, due to roundoff error."
					(lit1 closeTo: lit2) ifFalse: [^false]. self flag: 'just checking'. self halt]
				ifFalse:
					["any other discrepancy is a failure"
					^ false]]]]].
	^true! !

!CompiledMethod methodsFor: 'scanning' stamp: 'eem 6/19/2008 09:21'!
readsField: varIndex 
	"Answer whether the receiver loads the instance variable indexed by the 
	 argument."
	"eem 5/24/2008 Rewritten to no longer assume the compiler uses the
	 most compact encoding available (for EncoderForLongFormV3 support)."
	| varIndexCode scanner |
	varIndexCode := varIndex - 1.
	self isReturnField ifTrue: [^self returnField = varIndexCode].
	^(scanner := InstructionStream on: self) scanFor:
		[:b|
		b < 16
			ifTrue: [b = varIndexCode]
			ifFalse:
				[b = 128
					ifTrue: [scanner followingByte = varIndexCode and: [varIndexCode <= 63]]
					ifFalse:
						[b = 132
						 and: [(scanner followingByte between: 64 and: 95)
						 and: [scanner thirdByte = varIndexCode]]]]]! !

!CompiledMethod methodsFor: 'scanning' stamp: 'eem 5/24/2008 16:19'!
readsRef: literalAssociation 
	"Answer whether the receiver loads the argument."
	"eem 5/24/2008 Rewritten to no longer assume the compler uses the
	 most compact encoding available (for EncoderForLongFormV3 support)."
	| litIndex scanner |
	(litIndex := self indexOfLiteral: literalAssociation) = 0 ifTrue:
		[^false].
	litIndex := litIndex - 1.
	^(scanner := InstructionStream on: self) scanFor:
		[:b|
		b >= 64
		and:
			[b <= 95
				ifTrue: [b - 64 = litIndex]
				ifFalse:
					[b = 128
						ifTrue: [scanner followingByte - 192 = litIndex]
						ifFalse:
							[b = 132
							 and: [(scanner followingByte between: 128 and: 159)
							 and: [scanner thirdByte = litIndex]]]]]]! !

!CompiledMethod methodsFor: 'scanning' stamp: 'eem 5/24/2008 16:21'!
writesField: varIndex
	"Answer whether the receiver stores into the instance variable indexed
	 by the argument."
	"eem 5/24/2008 Rewritten to no longer assume the compler uses the
	 most compact encoding available (for EncoderForLongFormV3 support)."

	| varIndexCode scanner |
	self isQuick ifTrue: [^false].
	varIndexCode := varIndex - 1.
	^(scanner := InstructionStream on: self) scanFor:
		[:b|
		b >= 96
		and: [b <= 103
				ifTrue: [b - 96 = varIndexCode]
				ifFalse:
					[(b = 129 or: [b = 130])
						ifTrue: [scanner followingByte = varIndexCode and: [varIndexCode <= 63]]
						ifFalse:
							[b = 132
							 and: [(scanner followingByte between: 160 and: 223)
							 and: [scanner thirdByte = varIndexCode]]]]]]! !

!CompiledMethod methodsFor: 'scanning' stamp: 'eem 5/24/2008 16:14'!
writesRef: literalAssociation 
	"Answer whether the receiver stores into the argument."
	"eem 5/24/2008 Rewritten to no longer assume the compler uses the
	 most compact encoding available (for EncoderForLongFormV3 support)."
	| litIndex scanner |
	(litIndex := self indexOfLiteral: literalAssociation) = 0 ifTrue:
		[^false].
	litIndex := litIndex - 1.
	^(scanner := InstructionStream on: self) scanFor:
		[:b|
		(b = 129 or: [b = 130])
			ifTrue: [scanner followingByte - 192 = litIndex]
			ifFalse:
				[b = 132
				 and: [scanner followingByte >= 224
				 and: [scanner thirdByte = litIndex]]]]! !


!InstructionPrinter methodsFor: 'accessing' stamp: 'eem 5/29/2008 14:00'!
method: aMethod
	method :=  aMethod.
	printPC := true.
	indentSpanOfFollowingJump := false! !

!InstructionPrinter methodsFor: 'initialize-release' stamp: 'eem 5/29/2008 13:26'!
printInstructionsOn: aStream 
	"Append to the stream, aStream, a description of each bytecode in the
	 instruction stream."
	
	| end |
	stream := aStream.
	scanner := InstructionStream on: method.
	end := method endPC.
	oldPC := scanner pc.
	innerIndents := Array new: end withAll: 0.
	[scanner pc <= end] whileTrue:
		[scanner interpretNextInstructionFor: self]! !

!InstructionPrinter methodsFor: 'instruction decoding' stamp: 'eem 5/29/2008 14:02'!
jump: offset
	"Print the Unconditional Jump bytecode."

	self print: 'jumpTo: ' , (scanner pc + offset) printString.
	indentSpanOfFollowingJump ifTrue:
		[indentSpanOfFollowingJump := false.
		 innerIndents atAll: (scanner pc to: scanner pc + offset - 1) put: (innerIndents at: scanner pc - 1) + 1]! !

!InstructionPrinter methodsFor: 'instruction decoding' stamp: 'eem 5/29/2008 14:02'!
send: selector super: supered numArgs: numberArguments
	"Print the 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."

	self print: (supered ifTrue: ['superSend: '] ifFalse: ['send: ']) , selector.
	indentSpanOfFollowingJump := #(blockCopy: #closureCopy:copiedValues:) includes: selector! !

!InstructionPrinter methodsFor: 'printing' stamp: 'eem 5/29/2008 13:53'!
print: instruction 
	"Append to the receiver a description of the bytecode, instruction." 

	| code |
	stream tab: self indent.
	printPC ifTrue: [stream print: oldPC; space].
	stream tab: (innerIndents at: oldPC).
	stream nextPut: $<.
	oldPC to: scanner pc - 1 do: 
		[:i | 
		code := (method at: i) radix: 16.
		stream nextPut: 
			(code size < 2
				ifTrue: [$0]
				ifFalse: [code at: 1]).
		stream nextPut: code last; space].
	stream skip: -1.
	stream nextPut: $>.
	stream space.
	stream nextPutAll: instruction.
	stream cr.
	oldPC := scanner pc.
	"(InstructionPrinter compiledMethodAt: #print:) symbolic."
! !


!InstructionStream methodsFor: 'testing' stamp: 'eem 6/19/2008 23:32'!
willReallySend
	"Answer whether the next bytecode is a real message-send,
	not blockCopy:."

	| byte |
	byte := self method at: pc.
	^byte >= 131
	  and: [byte ~~ 200
	  and: [byte >= 176   "special send or short send"
		or: [byte <= 134 "long sends"	
			and: [| litIndex |
				"long form support demands we check the selector"
				litIndex := byte = 132
							ifTrue: [(self method at: pc + 1) // 32 > 1 ifTrue: [^false].
									self method at: pc + 2]
							ifFalse: [byte = 134
										ifTrue: [(self method at: pc + 1) bitAnd: 2r111111]
										ifFalse: [(self method at: pc + 1) bitAnd: 2r11111]].
				(self method literalAt: litIndex + 1) ~~ #blockCopy:]]]]! !

!InstructionStream methodsFor: 'testing' stamp: 'eem 5/16/2008 16:22'!
willSend
	"Answer whether the next bytecode is a message-send."

	| byte |
	byte := self method at: pc.
	^byte >= 131
	  and: [byte >= 176 "special send or short send"
		or: [byte <= 134]]	"long sends"! !


!ContextPart methodsFor: 'debugger access' stamp: 'eem 6/10/2008 09:42'!
tempNames
	"Answer a SequenceableCollection of the names of the receiver's temporary 
	 variables, which are strings."

	^ self debuggerMap tempNamesForContext: self! !

!ContextPart methodsFor: 'debugger access' stamp: 'eem 6/10/2008 09:47'!
tempsAndValues
	"Return a string of the temporary variabls and their current values"
	^self debuggerMap tempsAndValuesForContext: self! !

